ディスクスペースをオペレーティングシステムに戻すVACUUM


21

VACUUM通常、特別な場合を除いて、オペレーティングシステムにディスク領域を返しません。
ドキュメントから:

標準形式でVACUUMは、テーブルとインデックス内の無効な行バージョンを削除し、将来の再利用に使用可能なスペースをマークします。ただし、テーブルの最後の1つ以上のページが完全に空になり、排他的なテーブルロックを簡単に取得できる特別な場合を除いて、オペレーティングシステムに領域を返しません。対照的に、VACUUM FULLデッドスペースのない完全に新しいバージョンのテーブルファイルを書き込むことにより、アクティブにテーブルを圧縮します。これにより、テーブルのサイズが最小になりますが、時間がかかる場合があります。また、操作が完了するまで、テーブルの新しいコピー用に追加のディスク領域が必要です。

問題は、このデータベースの状態をどのone or more pages at the end of a table become entirely freeように達成できるかということです。これはを介して行うことができますがVACUUM FULL、実装するのに十分なスペースがありません。他の可能性はありますか?

回答:


29

OSにスペースを戻すには、を使用しますVACUUM FULL。その間、あなたは走ると思いますVACUUM FULL ANALYZE私はマニュアルを引用します

FULL

「フル」バキュームを選択します。これによりより多くのスペースを再利用できますが、時間がかかり、テーブルが排他的にロックされます。この方法では、テーブルの新しいコピーを書き込み、操作が完了するまで古いコピーを解放しないため、追加のディスク領域も必要です。通常、これは、テーブル内から大量のスペースを再利用する必要がある場合にのみ使用してください。

大胆な強調鉱山。

CLUSTER 副次的効果としてもそれを達成します。

VACUUM通常、Plain は目標を達成しません(「テーブルの最後にある1つ以上のページが完全に無料」)。行を並べ替えることはせず、機会が生じたときにファイルの物理的な終わりから空のページをプルーニングするだけです-マニュアルからの引用のように。

他のタプルが追加される前INSERTに行とバッチのバッチを作成すると、物理ファイルの最後に空のページをDELETE取得できます。または、十分な行が削除された場合、偶然に発生する可能性があります。

VACUUM FULLスペースの再利用を妨げる可能性のある特別な設定もあります。見る:

テスト用に表の最後に空のページを準備します

システム列ctidは、行の物理的な位置を表します。その列を理解する必要があります:

それを使って、最後のページからすべての行を削除してテーブルを準備できます。

DELETE FROM tbl t
USING (
   SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid     AS min_tid
        , (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
   FROM   tbl
   ORDER  BY ctid DESC
   LIMIT  1
   ) d
WHERE t.ctid BETWEEN d.min_tid AND d.max_tid;

現在、最後のページは空です。これは同時書き込みを無視します。そのテーブルに書き込みを行うのは自分だけであるか、干渉を避けるために書き込みロックを取得する必要があります。

クエリは、適格な行をすばやく識別するために最適化されます。aの2番目の数値は、tidunsignedとして格納されているタプルインデックスint2であり65535、そのタイプの最大値(2^16 - 1)であるため、これが安全な上限です。

SQL Fiddle(異なるケースの単純なテーブルを再利用します。)

行/テーブルのサイズを測定するツール:

ディスクがいっぱいです

これらの操作のいずれかを行うには、ディスク上にウィグルルームが必要です。/のpg_repack代わりとしてのコミュニティツールもあります。排他ロックを回避しますが、同様に機能するために空き領域が必要です。マニュアル:VACUUM FULLCLUSTER

ターゲットテーブルとインデックスの2倍の空きディスク領域が必要です。

最後の手段として、ダンプ/復元サイクルを実行できます。これにより、テーブルとインデックスからすべての膨張も削除されます。密接に関連した質問:

向こうの答えはかなり急進的です。状況が許す場合(外部キーや行の削除を妨げる他の参照がなく、テーブルへの同時アクセスがない場合)、次のことができます。

接続ディスクへのテーブルダンプリモートコンピュータディスクスペースの多くを-a--data-only):

リモートシェルから、テーブルデータをダンプします。

pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql

pgセッションでTRUNCATEは、テーブルは次のようになります。

-- drop all indexes and constraints here for best performance
TRUNCATE mytbl;

リモートシェルから、同じテーブルに復元します。

psql -h <host_name> -p <port> mydb -f db_mytbl.sql
-- recreate all indexes and constraints here

現在、デッド行や膨張はありません。

しかし、おそらくあなたはそれをよりシンプルにすることができますか?

  • 無関係なファイルを削除(移動)して、ディスクに十分なスペースを確保できますか?

  • VACUUM FULLテーブルを1つずつ小さくして、十分なディスク領域を解放できますか?

  • 肥大化したインデックスからディスク領域を実行REINDEX TABLEまたはREINDEX INDEX解放できますか?

あなたが何をするにしても、発疹ならないください。疑わしい場合は、最初にすべてを安全な場所にバックアップしてください。


アーウィン、申し訳ありませんが、私は真空がいっぱいになるのに十分なスペースがないことを言及するのを忘れました。質問を更新しました。
すべてが間違っている

@Zapadlo:更新された質問の章を追加しました。
アーウィンブランドステッター

包括的な回答をありがとう。実際に、偽の更新によってdbページの最後にデッド行を置くことができると考えました。つまりupdate table set field_1 = field_1、その操作が空き領域を返さなかった後にそのテーブルをバキュームしました。
すべてが間違っている

@ザパドロ:私が持っていたアイデアはすでに答えにあります。:)ディスク上にかなりの小刻みのスペースを必要とせずに、死んだタプルを並べ替えることができるツールを知りません。(そこに存在することができないという意味ではありません。)
アーウィンブランドステッター

彼らは、このツールがうまくいくと言っていますが、まだ試していません: code.google.com/p/pgtoolkit/source/browse/trunk/bin/...
間違った-について、すべて
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.