2

私は大きなテーブルをPostgresに持っています。Postgresパーティションのプルーニング

テーブル名はbigtableあると列は、次のとおりです。

integer |timestamp |xxx |xxx |...|xxx 
category_id|capture_time|col1|col2|...|colN 

私はcapture_time列のCATEGORY_IDと日付部分のモジュロ10の表をパーティション化しています。

パーティションテーブルは次のようになります。

CREATE TABLE myschema.bigtable_d000h0(
    CHECK (category_id%10=0 AND capture_time >= DATE '2012-01-01' AND capture_time < DATE '2012-01-02') 
) INHERITS (myschema.bigtable); 

CREATE TABLE myschema.bigtable_d000h1(
    CHECK (category_id%10=1 AND capture_time >= DATE '2012-01-01' AND capture_time < DATE '2012-01-02') 
) INHERITS (myschema.bigtable); 

私はWHERE句でCATEGORY_IDとcapture_timeでクエリを実行すると予想されるように、パーティションが剪定されていません。私はwhere句で正確な剰余基準(category_id%10=0)を追加した場合

explain select * from bigtable where capture_time >= '2012-01-01' and capture_time < '2012-01-02' and category_id=100; 

"Result (cost=0.00..9476.87 rows=1933 width=216)" 
" -> Append (cost=0.00..9476.87 rows=1933 width=216)" 
"  -> Seq Scan on bigtable (cost=0.00..0.00 rows=1 width=210)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h0 bigtable (cost=0.00..1921.63 rows=1923 width=216)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h1 bigtable (cost=0.00..776.93 rows=1 width=218)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h2 bigtable (cost=0.00..974.47 rows=1 width=216)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h3 bigtable (cost=0.00..1351.92 rows=1 width=214)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h4 bigtable (cost=0.00..577.04 rows=1 width=217)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h5 bigtable (cost=0.00..360.67 rows=1 width=219)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h6 bigtable (cost=0.00..1778.18 rows=1 width=214)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h7 bigtable (cost=0.00..315.82 rows=1 width=216)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h8 bigtable (cost=0.00..372.06 rows=1 width=219)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 
"  -> Seq Scan on bigtable_d000h9 bigtable (cost=0.00..1048.16 rows=1 width=215)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))" 

しかし、それはパーティションの剪定作業を行うためにどのような方法が正しくモジュロを追加することなく、あるの

explain select * from bigtable where capture_time >= '2012-01-01' and capture_time < '2012-01-02' and category_id=100 and category_id%10=0; 

"Result (cost=0.00..2154.09 rows=11 width=215)" 
" -> Append (cost=0.00..2154.09 rows=11 width=215)" 
"  -> Seq Scan on bigtable (cost=0.00..0.00 rows=1 width=210)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100) AND ((category_id % 10) = 0))" 
"  -> Seq Scan on bigtable_d000h0 bigtable (cost=0.00..2154.09 rows=10 width=216)" 
"    Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100) AND ((category_id % 10) = 0))" 

完璧に動作しますすべてのクエリの条件?

+0

が含まれるようにクエリを変更することであるという結論になってきましたか?私は9.xでパーティション化に関するプランナーにいくつかの改善があったと思う。 –

+0

制約を少し冗長にすることができます: 'CHECK(category_id%10 = 1 AND date_trunc( 'month'、capture_time)= '' 2012-01 -01 ':: date) ' –

+0

@a_horse_with_no_name私は9.1を使用しています – Dojo

答えて

1

: は、私が最も簡単な方法アウトは、使用しているバージョンモジュロ条件category_id%10=0

4

事はある:排他制約PostgreSQLのwill create an implicit indexため。あなたの場合、この索引は部分的なものになります。 'あなたは列の表現を使用しているだけでなく、その価値です。そして、(11-2の例を探してください)documentationに記載されています

PostgreSQLは異なる形で書かれている数学的に等価な表現を認識することができ、洗練された定理証明を持っていません。 (このような一般定理証明者は作成が非常に困難であるだけでなく、おそらく実際の使用には遅すぎるでしょう)。 それ以外の場合、述語条件はクエリのWHERE条件の一部と正確に一致する必要があります。そうしないと、インデックスが使用可能と認識されません。照合は、実行時ではなく照会計画時に行われます。

このように、CHECK制約の作成時に使用したのと同じ結果が得られるはずです。私は2つのアプローチを好むハッシュベースのパーティションについては

:、1つの設計で存在する最良の場合

  • は、値(あなたのケースでは10)の限定セットを取ることができ、フィールドを追加します。
  • あなたはタイムスタンプを指定するのと同じ方法が及ぶ範囲のハッシュを指定:あなたは

    • 最初のレベルに:MINVALUE < = CATEGORY_ID < MAXVALUE

    はまた、2・レベル・パーティションを作成することが可能ですcategory_idに基づいて10個のパーティションを作成します。

  • 2つ目のレベルでは、日付範囲に基づいて必要な量のパーティションを作成します。

私は常にパーティション化のために1つの列だけを使用しようとしますが、管理は簡単です。同じ問題を抱えている人のため

+0

あなたの入力に感謝します。私が投稿したコードは、1レベルの継承を使用して2レベルのパーティショニングを行っています。パフォーマンスは賢明ですが、実際の2レベルの継承よりも速く実行されます。最初のレベルでチェックするテーブルが少なく、適格な第1レベルのテーブルから継承したテーブルだけがスキャンされなければならないので、それは他の方法(あなたが示唆した方法)が速くなるはずです。しかし実際にはそれはより遅いです。 – Dojo

+0

パーティション・プルーニング・ロジックは遅くなりますが、実際のテーブル・スキャンではありません。どちらの場合も、オプティマイザはテーブルを正しくプルーニングしますが、2レベルの継承の場合は、プルーニングするパーティションを長く取ることを決定します。 – Dojo

+0

2レベルのパーティショニングについて興味深いのは、レベル1のテーブルをクエリでき、レベル2のパーティションのプルーニングに時間がかからないことです。私はこれを使用して、パフォーマンスを損なわない方法でデータをアーカイブすることができます。 – Dojo

関連する問題