0

次の方法で〜10 ^ 7行のテーブルを処理します。最後のN行を取得し、何らかの方法で更新してから、vacuumテーブルを削除します。最後に、のクエリを作成しますpg_total_relation_size。テーブルが終わるまでループが繰り返されます。各反復は数秒間続きます。上記を除いて、このテーブルに対する他のクエリはありません。問題は、テーブルサイズで同じ結果が得られることです。数時間に1回程度変化します。

だから問題は-postgresはテーブルサイズをどこかに保存するのか、それとも関数が呼び出されるたびにそれを計算するのか?つまり、テーブルのサイズは、処理されても実際には同じままですか?

4

1 に答える 1

3

あなたがしていることにもかかわらず、あなたのテーブルは実際にディスク上で同じサイズのままDELETEですVACUUMのドキュメントにVACUUMよると、通常VACUUMは、ライブ行を再配置せずにファイルの末尾から空き領域を切り捨てることによって解放できる場合にのみ、OSに領域を解放します。

PostgreSQLが他の新しい行に再利用できるという点で、このスペースはまだ「空き」です。PostgreSQLがOSに返さなかったスペースを再利用する方が、新しいスペースとの関係を拡張するよりもはるかに高速であるため、多くの場合、これが望ましいです。

Pgがこのスペースを返すだけではないもう1つの理由は、ファイルの終わりまで行が表示されない連続したチャンクである場合にのみ、OSにスペースを戻すことができるためです。これはあまり起こらないので、実際には、Pgはテーブルを圧縮し、ファイルシステムのデフラグのように、最後にスペースを解放できるようにするために、いくつかの行を移動する必要があります。これは非効率的で遅いプロセスであり、直感に反してテーブルへのアクセスが速くなるのではなく遅くなる可能性があるため、常に良い考えとは限りません。

ほとんどが完全に空ではない関係がある場合は、VACUUM FULL(Pg 9.0以降)またはCLUSTER(すべてのバージョン)を実行してスペースを解放する価値があります。テーブルを補充することを期待している場合、これは通常逆効果です。実際にはそのままにしておく方が良いです。

(「ライブ」や「可視」などの用語の意味については、Pgのテーブル編成を理解するのに役立つMVCCのドキュメントを参照してください。)

個人的には、あなたの場合はマニュアルをスキップVACUUMします。必要に応じて、自動真空をオンにします。本当に必要な場合は、テーブルをパーティション化して、パーティションごとに処理し、処理TRUNCATEが完了したら各パーティションを処理することを検討できます。

于 2013-03-25T10:35:50.003 に答える