- PostgreSQLでは カラムをDROPしても実際のデータは削除されない — ただメタデータ上で 「隠された状態」 になるだけ
- DROP COLUMNの後も内部的にはカラムが存在 するため、1600カラム制限 に到達する可能性がある
- データを完全に除去するには
VACUUM FULL または手動のテーブル再書き込み が必要
- これは性能最適化のための設計だが、GDPRのようなコンプライアンスの観点では注意が必要
- 「実際に何が起きるのか」を理解すると、問題解決、性能最適化、データ管理の面で有利
PostgreSQLでのDROP COLUMNの実際の動作
問題の状況: カラムを繰り返し追加・削除すると?
PostgreSQL内部では何が起きているのか?
カラム削除は「本当の削除」ではない
- PostgreSQLはデータを 8KBページ単位 で保存する
- カラムを物理的に削除するにはテーブル全体を 再書き込みする必要があり非効率
- その代わり、カラムを メタデータ上で 'dropped' 状態としてマークし、無視 する
pg_attribute システムテーブルで確認可能
SELECT attnum, attname, attisdropped FROM pg_attribute WHERE attrelid = 'test2'::regclass AND attnum > 0;
データファイルで確認する (pg_filedump を活用)
- PostgreSQLのデータファイルを解析すると、削除されたカラムの 値が実際に残っている ことを確認できる
- 以前のデータ (
Item 1) には3つのカラム値が存在する
- 削除後に挿入されたデータ (
Item 3) にはそのカラム値がなく、NULL として扱われる
削除されたカラムを実際に除去する方法
1. VACUUM FULL
- テーブル全体を再書き込みし、削除済みカラムのデータも除去 する
- 欠点: カラム自体は依然としてpg_attributeに存在し、「dropped」状態のまま
2. 手動のテーブル再書き込み
カラムDROPとGDPRの「忘れられる権利」の問題
注意事項
- PostgreSQLは MVCC方式 であるため、行削除後も VACUUMが完了するまではデータが残る
- OSレベルでも 物理削除ではなく「削除フラグ」処理の可能性がある
- 法的には「合理的な削除努力」が重要であり、物理ディスクを完全に消去するレベルまでは通常求められない
結論: DROP COLUMNは「隠す」だけで「削除」ではない
- 性能のための設計だが、カラムが蓄積すると 1600個制限に達する可能性がある
- 必要に応じて
VACUUM FULL または テーブル再書き込みでデータ整理 が必要
- システム設計やコンプライアンスの観点で PostgreSQLの内部動作を理解することは非常に有用
参考資料
3件のコメント
パフォーマンス最適化のための実装上の選択が、GDPRの忘れられる権利の問題とも関連づけて考えられるという視点が洞察に富んでいますね。個人データを適切にモデリングして削除することが核心であり、そこまで関連はないという結論に至る点も含めて、すっきりしています。
PostgreSQL は最近かなり人気ですが、MVCC の実装については redo/undo 領域が別個に存在する方式のほうが好みです。
redo/undo 領域はある程度リアルタイム性を犠牲にしても構わないので、低グレードのストレージを使ってコスト最適化の余地がありますし、
いつかは DB 全体にロックをかけて VACUUM FULL しなければならないという点も好みではありません。
VACUUM FULLはいずれ必ず実行しなければならないものなのでしょうか? 私が見たドキュメントのほとんどでは、しないほうがよいとされていました。私が見た資料の一つ:
https://www.depesz.com/2023/02/06/when-to-use-vacuum-full/