-
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 のカラムについて、確認した内容でした。