タイムスタンプでパーティション化されたテーブルを含む結合には、パーティション制約は使用されません


11

次のような分割テーブル構造があります。

CREATE TABLE measurements (
    sensor_id bigint,
    tx timestamp,
    measurement int
);

CREATE TABLE measurements_201201(
    CHECK (tx >= '2012-01-01 00:00:00'::timestamp without time zone 
       AND tx < ('2012-01-01 00:00:00'::timestamp without time zone + '1 mon'::interval))    
)INHERITS (measurements);
CREATE INDEX ON measurements_201201(sensor_id);
CREATE INDEX ON measurements_201201(tx);
CREATE INDEX ON measurements_201201(sensor_id, tx);
....

等々。各テーブルには約2,000万行があります。

WHERE節のセンサーのサンプルとタイムスタンプのサンプルをクエリすると、クエリプランは正しいテーブルが選択され、インデックスが使用されていることを示します。例:

SELECT *
FROM measurements
INNER JOIN sensors TABLESAMPLE BERNOULLI (0.01) USING (sensor_id)
WHERE tx BETWEEN '2015-01-04 05:00' AND '2015-01-04 06:00' 
    OR tx BETWEEN '2015-02-04 05:00' AND '2015-02-04 06:00' 
    OR tx BETWEEN '2014-03-05 05:00' AND '2014-04-07 06:00' ;

ただし、CTEを使用する場合、またはタイムスタンプ値をテーブルに配置する場合(一時テーブルにインデックスがあっても表示されません)。

WITH sensor_sample AS(
    SELECT sensor_id, start_ts, end_ts
    FROM sensors TABLESAMPLE BERNOULLI (0.01)
    CROSS JOIN (VALUES (TIMESTAMP '2015-01-04 05:00', TIMESTAMP '2015-01-04 06:00'),
        (TIMESTAMP '2015-02-04 05:00', TIMESTAMP '2015-02-04 06:00'),
        (TIMESTAMP  '2014-03-05 05:00', '2014-04-07 06:00') ) tstamps(start_ts, end_ts)
)

以下のようなもの

SET constraint_exclusion = on;
SELECT * FROM measurements
INNER JOIN sensor_sample USING (sensor_id)
WHERE tx BETWEEN start_ts AND end_ts

すべてのテーブルでインデックススキャンを実行します。これはまだ比較的高速ですが、クエリの複雑さが増すと、これはseqスキャンになり、パーティションテーブルの限られたサブセット(50のうち4-5)から最大40K行を取得するのに非常に遅くなる可能性があります。

このようなことが問題だと心配しています。

自明ではない式の場合、PostgresクエリプランナーがCHECK制約に依存できることをPostgresクエリプランナーに理解させるために、クエリ内で多かれ少なかれ逐語的な条件を繰り返す必要があります。冗長に見えても!

すべてのデータに対してシーケンススキャンを実行する可能性を減らすために、パーティション化とクエリ構造を改善するにはどうすればよいですか?


1
すばらしい質問ですが、EXPLAIN(ANALYZE、BUFFERS)の結果を貼り付けるとさらに良いでしょう
filiprem

回答:


1

制約ベースの除外[CBE]は、クエリが解析され、実際の関係にマップされて書き換えられた直後に、クエリ計画の初期段階で実行されます。(内部、Planner / Optimizerステージ)

プランナーは、「sensor_sample」テーブルの内容を想定できません。

したがって、クエリにハードコードされた値がない限り、プランナは「パーティション」を除外しません。

CTEバリアントで何が起こるかと思います... TABLESAMPLEを使用するとプランナーが制限され、サブクエリ内のリテラルが静的であっても、サブクエリ全体が揮発性として扱われる可能性があります。(それは私の推測です、私はプランナーコードの専門家ではありません

明るい面では、ネガティブな結果を伴うインデックススキャンは非常に高速です。(せいぜい単一ページのスキャンです!)したがって、10000を超えるパーティションがない限り、私は気にしません。

だから、あなたの質問に直接答えるには:

  • このデータ構造をこれ以上改善することはできません。

  • 索引スキャンについて-安価です。

  • 順次スキャンについて-独自の例でわかるように、可能であれば回避されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.