13

Postgres8.2でパーティショニングを使用するようにデータベースを再構築しました。クエリのパフォーマンスに問題があります。

SELECT *
FROM my_table
WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11'
ORDER BY id DESC
LIMIT 100;

テーブルには4500万行あります。パーティショニングの前に、これは逆インデックススキャンを使用し、制限に達するとすぐに停止します。

(time_stamp範囲で)パーティション分割した後、Postgresはマスターテーブルと関連するパーティションの完全なインデックススキャンを実行し、結果をマージして並べ替え、制限を適用します。これには時間がかかりすぎます。

私はそれを修正することができます:

SELECT * FROM (
  SELECT *
  FROM my_table_part_a
  WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11'
  ORDER BY id DESC
  LIMIT 100) t
UNION ALL
SELECT * FROM (
  SELECT *
  FROM my_table_part_b
  WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11'
  ORDER BY id DESC
  LIMIT 100) t
UNION ALL
  ... and so on ...
ORDER BY id DESC
LIMIT 100

これはすぐに実行されます。タイムスタンプが範囲外にあるパーティションは、クエリプランに含まれていません。

私の質問は次のとおりです。クエリプランナーがテーブル全体をスキャンするのを防ぐためにPostgres8.2で使用できるヒントや構文はありますが、マスターテーブルのみを参照する単純な構文を使用していますか?

基本的に、現在定義されている各パーティションに大きなUNIONクエリを動的に構築するという苦痛を回避できますか?

編集: constraint_exclusionを有効にしました(@Vinko Vrsalovicに感謝します)

4

3 に答える 3

7

Constraint Exclusion を試しましたか (リンク先のドキュメントのセクション 5.9.4)

制約の除外は、上記の方法で定義された分割テーブルのパフォーマンスを向上させるクエリ最適化手法です。例として:

 SET constraint_exclusion = on; 
 SELECT count(*) FROM measurement WHERE logdate >= DATE '2006-01-01'; 

制約の除外がなければ、上記のクエリは測定テーブルの各パーティションをスキャンします。制約の除外を有効にすると、プランナは各パーティションの制約を調べて、クエリの WHERE 句を満たす行をパーティションに含めることができないため、パーティションをスキャンする必要がないことを証明しようとします。プランナーがこれを証明できる場合、クエリ プランからパーティションを除外します。

EXPLAIN コマンドを使用して、constraint_exclusion がオンのプランとオフのプランの違いを表示できます。

于 2010-02-10T12:44:58.537 に答える
6

WHEREで条件をキャストすることで修正できたのと同様の問題がありました。例:(time_stamp列がtimestamptzタイプであると想定)

WHERE time_stamp >= '2010-02-10'::timestamptz and time_stamp < '2010-02-11'::timestamptz

また、テーブルのCHECK条件が同じように定義されていることを確認してください...例:CHECK(time_stamp <'2010-02-10' :: timestamptz)

于 2010-07-06T17:40:35.467 に答える