web-dev-qa-db-ja.com

バキューム/オートバキューム操作にはどのくらい時間がかかりますか?

私は、さまざまな役割を持つテーブルを含む大きな(数百のギグ)データベースを管理しています。一部のテーブルは、多数の挿入と削除のみを受け取り、その他のいくつかの挿入と多数の更新を受け取ります。

データベースは、16ギガバイトのRAMを搭載したDebian 6.0 AMD64システム上のPostgreSQL 8.4で実行されます。

問題は、テーブルの自動バキュームプロセスであり、完了するまでに非常に長い時間(日数)がかかることがあります。特定のバキュームコマンドにかかる時間を大まかに伝え、キャンセルするかどうかを決定できるようにしたいと考えています。また、postgresバキューム操作の進行状況インジケーターがあった場合、それは本当に役に立ちます。

編集:

防弾ソリューションは探していません。決定するには、デッドタプルの数または必要なI/Oバイトの大まかなヒントで十分です。 VACUUMがいつ終了するのかがわからないのは本当に面倒です。

pg_catalog.pg_stat_all_tablesには、無効なタプルの数の列があることがわかりました。したがって、以前にテーブルをANALYZEする必要があることを意味する場合でも、推定を行うことは可能です。一方、autovacuum_vacuum_thresholdautovacuum_vacuum_scale_factorの設定だけで、postgres自体がknowsテーブルの変更量について何かを証明し、おそらくDBAの手にも渡ることになる。

実行するクエリがわかりません。VACUUM VERBOSEを実行すると、テーブルだけでなく、それらのインデックスも処理されていることがわかります。

18
zaadeh

私のPostgreSQL(8.3)では、このトリックを使用します。

  1. pg_total_relation_size()を使用してテーブルのディスクサイズを取得します。これには、インデックスとTOASTサイズが含まれます。これはVACUUMが処理するものです。これにより、VACUUMが読み取る必要のあるバイト数がわかります。
  2. テーブルでVACUUMを実行します。
  3. pidプロセスのVACUUMを見つけます(pg_catalog.pg_stat_activity)。
  4. Linux Shellではwhile true; do cat /proc/123/io | grep read_bytes; sleep 60; done (どこ 123はpidです)-これは、これまでにプロセスがディスクから読み取ったバイト数を示しています。

これにより、VACUUMが1分間に何バイトを処理(読み取り)するかがおおよそわかります。 VACUUMはテーブル全体(インデックスとTOASTを含む)を読み取る必要があると思います。そのディスクサイズはステップ1でわかっています。

テーブルが十分に大きいため、ページの大部分をディスクから読み取る必要がある(Postgresの共有メモリには存在しない)ので、read_bytesフィールドは、進捗カウンターとして使用するのに十分です。

私がこれを行うたびに、プロセスによって読み取られた合計バイト数は合計リレーションサイズの5%を超えなかったので、このアプローチはあなたにとって十分に良いと思います。

35
Roman Hocke

これを判断するのは非常に困難です。 autovacuuming よりアグレッシブになる を調整するか、より穏やかにすることができます。しかし、マイルドに設定していて、遅れがあり、ベースI/O負荷が高すぎる場合、適切なバキューム状態に到達しないことがあり、プロセスが実行され、実行されていることがわかります。さらに、後のPostreSQLエディションではautovacuum機能が大幅に改善されており、これだけでそれらの1つ(できれば、最新のものとして9.2)に移動するのに十分かもしれません。

プログレスバーはいい考えに聞こえますが、意味のある実装はそれほど簡単ではないと思います。テーブルに一定の負荷がかかっているので、進行状況が明らかに後退している可能性があります(つまり、デッドローの数/パーセンテージは減少するのではなく増加します)。次に、どのような結論を導きますか?

9
dezso

私は this postthis post が役立つことを発見しましたが、他の人が述べたように、プロセスにはいくつかの個別の操作が含まれるため、真空の全体的な進行を計算するのは難しい場合があります。

このクエリを使用して、バキュームのテーブルスキャンの進行状況を監視します。これは、作業の大部分のようです。

SELECT heap_blks_scanned/cast(heap_blks_total as numeric)*100 as heap_blks_percent, progress.*, activity.query
FROM pg_stat_progress_vacuum AS progress
INNER JOIN pg_stat_activity AS activity ON activity.pid = progress.pid;

ただし、これには、後で行われるインデックススキャンは含まれず、大量のインデックスがある場合は、それよりも長くても長くはかからない可能性があります。残念ながら、インデックスのスキャン/バキュームを監視する方法はありません。

4
Cerin

私たちの生産では、最大のテーブルの1つにこのログがありました。

pages: 0 removed, 1801722 remain
tuples: 238912 removed, 42582083 remain, 1396 are dead but not yet removable
buffer usage: 9477565 hits, 3834218 misses, 2220101 dirtied
avg read rate: 2.976 MB/s, avg write rate: 1.723 MB/s
system usage: CPU 68.47s/177.49u sec elapsed 10065.08 sec

これは、明らかに最悪のリソース消費であり、他のすべてのテーブルの所要時間は2秒未満です。

これらのタイプのログを表示するには、これを実行する必要があります。

alter system set log_autovacuum_min_duration TO 5; 

(5 ms)、構成ファイルを再ロードします。

3
stonelazy