Postgres 9.2データベースを最適化して、日付制限のあるクエリを高速化しようとしています。
私はtimestamp
列を持っていますが、ほとんどの場合、いつか求めているので、timestamp
からdate
を解析してインデックスを作成しました。
CREATE INDEX foo_my_timestamp_idx
ON foo
USING btree
((my_timestamp::date) DESC);
ここで、パフォーマンスを向上させるために、上記のインデックスを使用してI CLUSTER
foo
テーブルを作成します。
CLUSTER foo USING foo_my_timestamp_idx;
SQL-CLUSTER のマニュアルによると、テーブル
インデックス情報に基づいて物理的に並べ替えられます
テーブルのPKを使用する他のクエリのパフォーマンスに影響があるかどうか疑問に思います(id_foo
)。欠点はありますか?
はい、マイナス面もあります。別のクエリが日付で特定されない別のデータセグメントを参照する場合、行がより多くのデータページに分散されていると、パフォーマンスに影響する可能性があります。最初のクエリの利益とまったく同じです。それはあなたの質問にない情報に完全に依存しています。
テーブルのPKを使用する他のクエリ(id_fooとしましょう)
それは anything のようになります。それはあなたが持っているものとあなたが何をクエリするか正確にに依存します。単一の行のクエリはどちらの方法でも影響を受けませんが、複数の行は影響を受ける可能性があります。
CLUSTER
はVACUUM FULL
が行うような元の状態でテーブルを書き換えます(無効なタプルを削除し、テーブルの物理サイズを圧縮し、書き換えます)インデックス)したがって、並べ替え順序に関係なく、読み取りパフォーマンスにすぐにプラスの影響を与える可能性があります。 (VACUUM FULL
を使用するのと同じです。)CLUSTER
の後に、プレーン VACUUM
を実行して、可視性マップを更新する も実行できます-これにより、インデックスのみを許可できますスキャン。
CLUSTER
のすべての利点は、書き込み頻度とともに減少します。
また、テーブルへの更新が多い場合、CLUSTER
は、同じデータページでHOT更新用の「ゆらぎの部屋」を削除することにより、実際に hurt 書き込みパフォーマンスを実現できます。 FILLFACTOR
を100未満に設定すると、その影響に対抗できる場合があります。ここでも、更新された行の局所性などに依存します。
関連:
いずれにせよ、私はおそらく not my_timestamp::date
にインデックスを付けてクラスタ化しますが、my_timestamp
に直接。何も失わず、何かが得られた。キャストは非常に安価ですが、まったくキャストしない方が安いです。また、インデックスはより多くのクエリをサポートできます。
CREATE INDEX foo_my_timestamp_idx ON foo (my_timestamp);
date
はディスク上で4バイトのみを占有し、timestamp
は8バイトを占有しますが、通常、違いは配置のパディングによって失われ、両方のインデックスはを正確に持ちます同じサイズ。
式インデックスに起因する同じ日の複数の行の順序は任意です。それでも2つの同じタイムスタンプが存在する可能性がありますが、通常はほとんどあり得ない6つの小数桁があります。それとは別に、行の確定的な順序を取得します。これにはさまざまな利点があります。
Postgresは実質的に高速で前方にインデックスを逆方向に読み取ることができるため、DESC
キーワードのWordも削除しました。 (ただし、マルチカラムインデックスではソート順が重要です!)詳細:
の代わりに:
SELECT * FROM foo
WHERE my_timestamp::date = '2016-07-25';
あなたは今使うでしょう:
SELECT * FROM foo
WHERE my_timestamp >= '2016-07-25' -- this is a timestamp literal now
WHERE my_timestamp < '2016-07-26';
同じパフォーマンス。
列の時間コンポーネントが必要ない場合は、まったく、列をdate
に変換します...
CLUSTER
をロールバックするには?単一のテーブルのCLUSTER
は、トランザクションがコミットされていない限り、他の通常のコマンドと同様にROLLBACK
を使用してロールバックできます。
しかし、 私はマニュアルを引用しています :
パラメータなしの
CLUSTER
は、現在のデータベースで以前にクラスタ化されたすべてのテーブルを再呼び出しします。これは、呼び出し元のユーザーが所有しているテーブル、またはスーパーユーザーから呼び出された場合はそのようなすべてのテーブルです。この形式のCLUSTER
は、トランザクションブロック内では実行できません。
いつでもCLUSTER
を別のインデックスで実行して、行の物理的な順序をもう一度変更できます。