TECH BLOG
技術ブログ

ARTICLE

  • 2022-01-18 PostgreSQL

    pg_attribute.attname が pg.dropped.xx のカラム

pg_attribute というシステムカタログには、各テーブルの列情報が格納されています。
pg_attribute を眺めていると、「........pg.dropped.4........」というような見慣れないカラム名(attname)となっているカラムがありました。
こんなカラム名をつけた覚えはないので、公式ドキュメントを確認したところ、これは ALTER TABLE コマンドで削除されたカラムのようであることが分かりました。

PostgreSQL 13.1文書 - ALTER TABLE -

https://www.postgresql.jp/document/13/html/sql-altertable.html

DROP COLUMN構文は、列を物理的には削除せず、SQLの操作に対して不可視にします。

ALTER TABLE コマンドでカラムを削除した場合、物理的には削除されない、つまり論理削除となるようです。

検証

実際にテーブルのカラムを削除して、挙動を確認してみました。

1. テーブルのカラムを確認

まずはテストテーブルを用意します。
名前は test_table とします。
test_table の定義は下記のとおりです。

postgres=# \d test_table

                Table "public.test_table"
    Column     |  Type   | Collation | Nullable | Default 
---------------+---------+-----------+----------+---------
 id            | integer |           | not null | 
 no            | integer |           |          | 
 category_code | integer |           |          | 
 spare_code    | integer |           |          | 
Indexes:
    "test_table_pkey" PRIMARY KEY, btree (id)

pg_attribute を参照して、カラム名(attname)を確認します。
ただ、pg_attribute にはテーブル名は持っていないので、テーブル名で絞り込みたい場合は、pg_class と結合する必要があります。

postgres=# SELECT cl.relname, at.attnum, at.attname 
FROM pg_class cl 
INNER JOIN pg_attribute at 
ON cl.oid = at.attrelid 
WHERE cl.relname = 'test_table' 
ORDER BY at.attnum;

  relname   | attnum |    attname    
------------+--------+---------------
 test_table |     -6 | tableoid
 test_table |     -5 | cmax
 test_table |     -4 | xmax
 test_table |     -3 | cmin
 test_table |     -2 | xmin
 test_table |     -1 | ctid
 test_table |      1 | id
 test_table |      2 | no
 test_table |      3 | category_code
 test_table |      4 | spare_code
(10 rows)

test_table がもつカラムを無事に参照できました。
pg_attribute.attnum が 0 未満のカラムは PostgreSQL が自動的に作成するカラムのようです。
絞り込みを行う WHERE 句に 0 < pg_attribute.attnum を加えてもよいかもしれません。

2. テストテーブルのカラムを削除
postgres=# ALTER TABLE test_table DROP COLUMN spare_code;
ALTER TABLE

ALTER TABLE で test_table の spare_code を削除しました。
もう一度、pg_attribute を確認してみます。

postgres=# SELECT cl.relname, at.attnum, at.attname 
FROM pg_class cl 
INNER JOIN pg_attribute at 
ON cl.oid = at.attrelid 
WHERE cl.relname = 'test_table' 
ORDER BY at.attnum;
  relname   | attnum |           attname            
------------+--------+------------------------------
 test_table |     -6 | tableoid
 test_table |     -5 | cmax
 test_table |     -4 | xmax
 test_table |     -3 | cmin
 test_table |     -2 | xmin
 test_table |     -1 | ctid
 test_table |      1 | id
 test_table |      2 | no
 test_table |      3 | category_code
 test_table |      4 | ........pg.dropped.4........
(10 rows)

spare_code だったカラム名が「........pg.dropped.4........」となりました。
pg.dropped につづく 4 という数字は attnum に該当するようです。
例えば、attnum = 2 の no を削除した場合、「........pg.dropped.2........」になります。

3. テストテーブルのカラムを追加
postgres=# ALTER TABLE test_table ADD COLUMN spare_code INTEGER;
ALTER TABLE

test_table に spare_code カラムを再び追加してみました。
pg_attribute を確認します。

postgres=# SELECT cl.relname, at.attnum, at.attname 
FROM pg_class cl 
INNER JOIN pg_attribute at 
ON cl.oid = at.attrelid 
WHERE cl.relname = 'test_table' 
ORDER BY at.attnum;
  relname   | attnum |           attname            
------------+--------+------------------------------
 test_table |     -6 | tableoid
 test_table |     -5 | cmax
 test_table |     -4 | xmax
 test_table |     -3 | cmin
 test_table |     -2 | xmin
 test_table |     -1 | ctid
 test_table |      1 | id
 test_table |      2 | no
 test_table |      3 | category_code
 test_table |      4 | ........pg.dropped.4........
 test_table |      5 | spare_code
(11 rows)

当然ではありますが attnum = 5 に spare_code カラムが追加されました。

削除されたカラムの扱いについて

ALTER TABLE DROP COLUM で削除されたカラムは、物理的にはテーブル上に存在していますが、SQL の実行時には無視されます(存在しないものとして扱われます)。
そのため、SQL で削除されたカラムを参照できませんし、削除されたカラムが存在しても SQL のパフォーマンスには影響ないと考えられます。

ただ、削除したカラムが pg_attribute で確認できてしまうのは「落ち着かない」「やっぱり物理的にカラムを削除したい」という場合には、やはりテーブルを再作成する必要があります。
「カラムを削除」→「テーブルのデータを退避」→「テーブル削除」→「テーブル作成」→「テーブルにデータを復元」
という手順でカラムを物理的に削除できます。
ただ、ここまでしてカラムを物理的に削除する必要もない、というのも正直なところです。

以上、pg_attribute.attname が pg.dropped.xx のカラムについて、確認した内容でした。

CATEGORY

ARCHIVE

PostgreSQLの
ハイパフォーマンスチューニングのご相談は
株式会社インサイトまで
お気軽にお問い合わせください。

CONTACT