すべてのプロダクト
Search
ドキュメントセンター

PolarDB:パーティションの剪定

最終更新日:Jul 01, 2024

PolarDB for PostgreSQL (Compatible with Oracle) は、パーティションプルーニング機能をサポートしています。これにより、パーティションテーブルに対するクエリを大幅に高速化できます。

概要

パーティションプルーニングを有効にすると、クエリプランナーは各パーティションの定義を調べ、クエリのWHERE句を満たす行を含めることができなかったため、パーティションをスキャンする必要がないことを証明しようとします。 プランナーがこれを証明できる場合、クエリプランからパーティションを除外または削除します。 パーティションプルーニングにより、ディスクから取得するデータ量が大幅に削減され、処理時間が短縮されるため、クエリのパフォーマンスとリソース使用率が向上します。

実際のSQL文に応じて、PolarDB for PostgreSQL (Compatible with Oracle) は静的または動的プルーニングを使用できます。

  • 静的プルーニングは、事前にアクセスされたパーティションに関する情報を使用して、コンパイル中に発生します。 静的プルーニングの一般的なシナリオは、SQL文にパーティションキー列に定数リテラルを持つWHERE条件が含まれている場合です。

  • 動的プルーニングは実行時に行われます。つまり、ステートメントによってアクセスされる正確なパーティションは事前にわかっていません。 動的プルーニングのシナリオ例は、WHERE条件が演算子または関数を使用する場合です。

パーティションプルーニングは、プルーニングが行われるオブジェクトの統計に影響し、ステートメントの実行計画にも影響します。

システムは、所望のレコードを含むことができるパーティションのみにデータスキャンを制限する。 動的プルーニングと静的プルーニングの両方で、実行計画の不要なパーティションが省略され、パフォーマンスが向上します。

パーティションプルーニングと制約除外

パーティションプルーニングと制約除外は、次の点で異なります。

  • システムがパーティションプルーニングを実行するとき、パーティション間の関係を考慮に入れる。 これは、制約除外の場合には当てはまらない。

    例えば、リスト・パーティション・テーブル内の特定のレコードを探すとき、パーティション・プルーニングに従って、システムは、レコードが格納されているパーティションを知る。 しかしながら、制約除外中に、システムは、各パーティションに対して定義された制約をチェックしなければならない。

  • パーティションのプルーニングは、プランナが見る必要のあるパーティションの数を減らすために、最適化段階の初期段階で行われます。 しかし、制約ベースの除外は、最適化の後の段階で行われる。

異なる段階でのパーティションの剪定

PolarDB for PostgreSQL (Oracleと互換) では、条件は不変、安定、および揮発性に分類されます。 カテゴリごとに、対応するパーティション剪定方法があります。

  • 定数リテラルなどの不変条件の場合、システムはオプティマイザステージでパーティションプルーニングを実行します。

  • now() 関数などの安定した条件の場合、パーティションプルーニングは早期の実行段階で行われます。

  • random() 関数などのランダムな条件の場合、パーティションプルーニングは後の実行段階で実行されます。

オプティマイザステージでのパーティションの剪定

この例では、logdateフィールドをパーティションキーとして使用して、measurement_y2023q1measurement_y2023q2measurement_y2023q3measurement_y2023q4の4つのパーティションを含むテーブル測定が作成されます。 各パーティションは、4分の1の2023のデータに対応します。

CREATE TABLE measurement(
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);
CREATE TABLE measurement_y2023q1 PARTITION OF measurement
    FOR VALUES FROM ('2023-01-01') TO ('2023-04-01');
CREATE TABLE measurement_y2023q2 PARTITION OF measurement
    FOR VALUES FROM ('2023-04-01') TO ('2023-07-01');
CREATE TABLE measurement_y2023q3 PARTITION OF measurement
    FOR VALUES FROM ('2023-07-01') TO ('2023-10-01');
CREATE TABLE measurement_y2023q4 PARTITION OF measurement
    FOR VALUES FROM ('2023-10-01') TO ('2024-04-01');

クエリを実行して、logdate値が2023-10-01以上のすべてのレコードを取得します。 EXPLAINコマンドから返された実行プランでは、最初の4分の3のレコードはすべてプルーニングされます。これは、logdate値がlogdate >= DATE '2023-10-01 '条件を満たしていないためです。 したがって、これらのレコードは実行中にスキャンされません。 logdateパーティションキーの条件は定数リテラルDATE '2023-10-01 'であるため、このパーティションプルーニングはオプティマイザステージで実行されます。

EXPLAIN SELECT * FROM measurement WHERE logdate >= DATE '2023-10-01';
                                 QUERY PLAN                                  
-----------------------------------------------------------------------------
 Append  (cost=0.00..34.09 rows=567 width=20)
   ->  Seq Scan on measurement_y2023q4  (cost=0.00..31.25 rows=567 width=20)
         Filter: (logdate >= '01-OCT-23 00:00:00'::date)
(3 rows)

初期のエグゼキューター段階でのパーティションの剪定

この例では、テーブルとクエリは同じですが、条件は定数値からnow() 式に変更されます。 この式はオプティマイザでは計算できませんが、実行ステージの早い段階で計算できます。 2023、クエリが7月の日に実行されると仮定すると、実行計画は、最初の2つのクォーターのパーティションがプルーニングされることを示す (Subplans Removed: 2によって示される) 。 measurement_y2023q3およびmeasurement_y2023q4パーティションのみがスキャンされます。 logdateパーティションキーの条件は、この段階で計算できる安定した式now() であるため、このパーティションプルーニングは初期の実行段階で実行されます。

EXPLAIN SELECT * FROM measurement WHERE logdate >= now();
                                 QUERY PLAN                                  
-----------------------------------------------------------------------------
 Append  (cost=0.00..153.34 rows=2268 width=20)
   Subplans Removed: 2
   ->  Seq Scan on measurement_y2023q3  (cost=0.00..35.50 rows=567 width=20)
         Filter: (logdate >= now())
   ->  Seq Scan on measurement_y2023q4  (cost=0.00..35.50 rows=567 width=20)
         Filter: (logdate >= now())
(6 rows)

後のエグゼキューター段階でのパーティションの剪定

この場合も、テーブルとクエリは同じですが、今回は、条件は揮発性の式 (select to_date('2023-10-1 ')) です。 後のエグゼキュータ段階でのみ計算できます。

実行計画に示されているように、最初の4分の3のパーティションにはタグが付けられ (never executed) 、つまりプルーニングされます。 このプルーニングモードは、volatile式、サブクエリ、サブ結合、および結合条件に対して発生します。

EXPLAIN ANALYZE SELECT * FROM measurement WHERE logdate >= (select  to_date('2023-10-1'));
                                                      QUERY PLAN                                                       
-----------------------------------------------------------------------------------------------------------------------
 Append  (cost=0.01..136.35 rows=2268 width=20) (actual time=0.067..0.068 rows=0 loops=1)
   InitPlan 1 (returns $0)
     ->  Result  (cost=0.00..0.01 rows=1 width=8) (actual time=0.051..0.053 rows=1 loops=1)
   ->  Seq Scan on measurement_y2023q1  (cost=0.00..31.25 rows=567 width=20) (never executed)
         Filter: (logdate >= $0)
   ->  Seq Scan on measurement_y2023q2  (cost=0.00..31.25 rows=567 width=20) (never executed)
         Filter: (logdate >= $0)
   ->  Seq Scan on measurement_y2023q3  (cost=0.00..31.25 rows=567 width=20) (never executed)
         Filter: (logdate >= $0)
   ->  Seq Scan on measurement_y2023q4  (cost=0.00..31.25 rows=567 width=20) (actual time=0.004..0.004 rows=0 loops=1)
         Filter: (logdate >= $0)