44

大規模なデータセットを含むテーブルがあり、このテーブルには削除したい 3 つの列があります。
問題は、Postgres がそれにどう対処するかということです。

すべてのエントリをウォークスルーしますか、それともオーバーヘッドをあまりかけずにマッピング情報を更新するだけですか? ALTER TABLEこの特定のケースでは、スワップテーブルを作成できますか、それとも使用する必要がありますか?

また、違いがある場合は、3 つの列すべてが固定長 (2 つの整数と 1 つの数値) になります。

既に質問されている場合は申し訳ありませんが、Google は関連する質問/記事を見つけることができませんでした...

4

2 に答える 2

57

ALTER TABLE DROP COLUMN は、システム テーブルの列を無効にするだけです。これは非常に高速ですが、ヒープ ファイルからデータを削除しません。後で VACUUM FULL を実行して、割り当てられたファイル スペースを圧縮する必要があります。したがって、ALTER TABLE DROP COLUMN は非常に高速です。また、ファイルを圧縮するには、低速の (排他的 LOCK を使用して) VACUUM FULL を呼び出す必要があります。

于 2013-03-29T08:59:56.427 に答える
50

Google はこの質問には役に立たないかもしれませんが、マニュアルが失敗することはめったにありません:

フォームは列を物理的に削除するのDROP COLUMNではなく、単に SQL 操作から見えなくするだけです。テーブルでの後続の挿入操作と更新操作では、列に null 値が格納されます。したがって、列を削除するのは簡単ですが、削除された列が占有していたスペースが再利用されないため、テーブルのディスク上のサイズがすぐに減少するわけではありません。既存の行が更新されると、時間の経過とともにスペースが再利用されます。

と:

テーブルの即時書き換えを強制するにはVACUUM FULL、 、 または書き換えを強制するCLUSTERのいずれかの形式を使用できますALTER TABLE。これにより、テーブルに意味的に目に見える変更はありませんが、不要になったデータは削除されます。

具体的にはattisdropped、システム カタログ テーブルの列pg_attributeが に設定されtrueます。

副作用

マイナーな副作用があります (Chris が指摘したように):

  • 更新または新しく挿入された行は、表示列に NULL がない場合でも、新しい行ごとに NULL ビットマップを強制する非表示の NULL 値を格納します。元の (現在は非表示になっている) 列の値が保持されるため、既存の行には影響しません。

  • NULL ビットマップは、表示されているすべての列と削除された列をカバーするのに十分な大きさである必要があります。まれに、これにより NULL ビットマップが拡大される場合があります。有効サイズについて:

  • ドロップされた列は、許可されている最大値に対してカウントされます (とにかくスクレイピングすべきではありません)。

  • 現在 (Postgres 13) ゾンビ列を完全に取り除く簡単な方法はありません。上記のテーブルの書き換えでは、非表示の値が NULL に置き換えられます (ほとんどすべてのスペースが再利用されます) が、削除された列はシステム カタログから削除されません。さえないTRUNCATE。新しいテーブルの作成 (またはダンプ/復元サイクル) のみがそれを行います。

于 2013-03-29T09:01:17.733 に答える