web-dev-qa-db-ja.com

列Aのクラスター化インデックスは、Aで順序付けられたテーブルを作成することと同じですか?

バージョン9.0の PostgreSQL公式ドキュメントを読む 興味深い escamotage を読みました大きなテーブルでは、CLUSTERよりもパフォーマンスが優れています。

CLUSTERコマンドは、指定したインデックスを使用してスキャンすることにより、元のテーブルを並べ替えます。行がインデックス順にテーブルからフェッチされるため、大きなテーブルではこれが遅くなる可能性があります。テーブルが無秩序である場合、エントリはランダムなページにあり、移動される行ごとに1つのディスクページが取得されます。 (PostgreSQLにはキャッシュがありますが、大きなテーブルの大部分はキャッシュに収まりません。)テーブルをクラスター化するもう1つの方法は、次のものを使用することです。

  CREATE TABLE newtable AS
    SELECT * FROM table ORDER BY columnlist;

postgreSQLのソートコードを使用して目的の順序を生成します。これは通常、無秩序なデータのインデックススキャンよりもはるかに高速です。次に、古いテーブルを削除し、ALTER TABLE ... RENAMEを使用してnewtableの名前を古い名前に変更し、テーブルのインデックスを再作成します。このアプローチの大きな欠点は、OID、制約、外部キーの関係、付与された特権、およびテーブルの他の補助的なプロパティが保持されないことです。そのようなアイテムはすべて手動で再作成する必要があります。別の欠点は、この方法ではテーブル自体とほぼ同じサイズのソート一時ファイルが必要になるため、ディスク使用量のピークがテーブルサイズの2倍ではなく約3倍になることです。

問題は、この提案が9.0を超える公式ドキュメントに表示されないことです。

私の質問は、2つの大きなテーブル(1つは〜750M行、もう1つは〜1650M行)に対するCLUSTER操作と平均ディスク書き込み/公式ドキュメントで説明されているCLUSTERアルゴリズムにより、読み取り速度は3MB/sです。大きなテーブルでは処理が遅いため、「インデックスに関連付けられた列に順序付けられたテーブルを作成する」というトリックは避けたいと思います。これにより、DB処理の日数を節約できます。

3
pietrop

@ dezsoがコメントしたように 、新しいテーブルを作成し、古いバージョンを削除すると、以前のバージョンでは以前より高速でしたが、9.1の新しい実装ではそれ以上ではありません。

CLUSTERの最も一般的な問題は、テーブルへの排他的ロックが必要なことです。これは、テーブルへの同時アクセスではうまくいきません。

this問題の解決策は pg_repack であり、これはテーブルのみ。

一般に、 サーバー設定がタスクに適している であることを確認してください。 maintenance_work_mem の高設定(大量のRAM)は、大きなテーブルでCLUSTERCREATE INDEXの両方に役立ちます。標準設定はwayには小さすぎます。詳細はリンク先をご覧ください。

SET LOCALを使用するトランザクションでは、一時的に非常に高く設定し、それ以外の場合は妥当な設定のままにしておくことができます。

BEGIN;
SET LOCAL maintenance_work_mem = ????MB; -- find the sweet spot
CLUSTER tbl;
COMMIT;

可能であれば、操作全体をRAMに収めるのに十分な高さに設定します。

もっと:

4