テーブルパーティションのサポート - Amazon Aurora

テーブルパーティションのサポート

Aurora PostgreSQL クエリプラン管理 (QPM) は、以下のバージョンで宣言的テーブルパーティショニングをサポートしています。

  • 15.3 以降の 15 バージョン

  • 14.8 以降の 14 バージョン

  • 13.11 以降の 13 バージョン

詳細については、「テーブルのパーティション」を参照してください。

テーブルパーティションの設定

Aurora PostgreSQL QPM でテーブルパーティションをセットアップするには、以下の手順を実行してください。

  1. DB クラスターパラメータグループで apg_plan_mgmt.plan_hash_version を 3 以上に設定します。

  2. クエリプラン管理を使用し、apg_plan_mgmt.dba_plans ビューにエントリがあるデータベースに移動します。

  3. apg_plan_mgmt.validate_plans('update_plan_hash') を呼び出して、プランテーブルの plan_hash 値を更新します。

  4. クエリプラン管理が有効になっていて、apg_plan_mgmt.dba_plans ビューにエントリがあるすべてのデータベースについて、手順 2~3 を繰り返します。

これらのパラメータの詳細については、「Aurora PostgreSQL クエリ計画管理のパラメータリファレンス」を参照してください。

テーブルパーティションのプランのキャプチャ

QPM では、さまざまなプランが plan_hash 値によって区別されます。plan_hash がどのように変化するかを理解するには、まず、同様の種類のプランを理解する必要があります。

Append ノードレベルで蓄積されるアクセス方法、数字を取り除いたインデックス名、および数字を取り除いたパーティション名の組み合わせが同じであれば、プランは同じと見なされます。プランでアクセスされる特定のパーティションは重要ではありません。次の例では、テーブル tbl_a は 4 つのパーティションで作成されます。

postgres=>create table tbl_a(i int, j int, k int, l int, m int) partition by range(i); CREATE TABLE postgres=>create table tbl_a1 partition of tbl_a for values from (0) to (1000); CREATE TABLE postgres=>create table tbl_a2 partition of tbl_a for values from (1001) to (2000); CREATE TABLE postgres=>create table tbl_a3 partition of tbl_a for values from (2001) to (3000); CREATE TABLE postgres=>create table tbl_a4 partition of tbl_a for values from (3001) to (4000); CREATE TABLE postgres=>create index t_i on tbl_a using btree (i); CREATE INDEX postgres=>create index t_j on tbl_a using btree (j); CREATE INDEX postgres=>create index t_k on tbl_a using btree (k); CREATE INDEX

クエリが検索するパーティションの数に関係なく、単一のスキャン方法を使用して tbl_a をスキャンするため、次のプランは同じと見なされます。

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 999 and j < 9910 and k > 50; QUERY PLAN ------------------------------------------------------------------- Seq Scan on tbl_a1 tbl_a Filter: ((i >= 990) AND (i <= 999) AND (j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -694232056 (3 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN ------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -694232056 (6 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a3 tbl_a_3 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -694232056 (8 rows)

次の 3 つのプランも同じとみなされます。親レベルで、アクセス方法、数字を取り除いたインデックス名、および数字を取り除いたパーティション名は、SeqScan tbl_aIndexScan (i_idx) tbl_a であるためです。

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a2_i_idx on tbl_a2 tbl_a_2 Index Cond: ((i >= 990) AND (i <= 1100)) Filter: ((j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993736942 (7 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a3_i_idx on tbl_a3 tbl_a_3 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993736942 (10 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 3100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a3 tbl_a_3 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a4_i_idx on tbl_a4 tbl_a_4 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993736942 (11 rows)

子パーティション内の出現順序や出現回数が異なっていても、アクセス方法、数字を取り除いたインデックス名、および数字を取り除いたパーティション名は、上記の各プランの親レベルで同じです。

ただし、次の条件のいずれかが満たされる場合、プランは異なると見なされます。

  • プランで追加のアクセス方法が使用される。

    postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Bitmap Heap Scan on tbl_a3 tbl_a_3 Recheck Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Bitmap Index Scan on tbl_a3_i_idx Index Cond: ((i >= 990) AND (i <= 2100)) SQL Hash: 1553185667, Plan Hash: 1134525070 (11 rows)
  • プラン内のどのアクセス方法もそれ以上使用されない。

    postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -694232056 (6 rows)
  • インデックスメソッドに関連付けられたインデックスが変更された。

    postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a2_j_idx on tbl_a2 tbl_a_2 Index Cond: (j < 9910) Filter: ((i >= 990) AND (i <= 1100) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993343726 (7 rows)

テーブルパーティションプランの実施

パーティションテーブルについて承認されたプランは、位置対応で実施されます。プランはパーティションに固有ではなく、元のクエリで参照されているプラン以外のパーティションにも適用できます。プランには、最初に承認されたアウトラインとは異なる数のパーティションにアクセスするクエリを強制する機能もあります。

例えば、承認されたアウトラインが次のプランに関するものであるとします。

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a3_i_idx on tbl_a3 tbl_a_3 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993736942 (10 rows)

この場合、このプランは、2、4、またはそれ以上のパーティションを参照する SQL クエリにも適用できます。これらのシナリオで、2 パーティションと 4 パーティションのアクセスについて考えられるプランは以下のとおりです。

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN ---------------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 1100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) Note: An Approved plan was used instead of the minimum cost plan. SQL Hash: 1553185667, Plan Hash: -993736942, Minimum Cost Plan Hash: -1873216041 (8 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 3100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a3_i_idx on tbl_a3 tbl_a_3 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a4 tbl_a_4 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) Note: An Approved plan was used instead of the minimum cost plan. SQL Hash: 1553185667, Plan Hash: -993736942, Minimum Cost Plan Hash: -1873216041 (12 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 3100 and j < 9910 and k > 50; QUERY PLAN ---------------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a3_i_idx on tbl_a3 tbl_a_3 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) -> Index Scan using tbl_a4_i_idx on tbl_a4 tbl_a_4 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) Note: An Approved plan was used instead of the minimum cost plan. SQL Hash: 1553185667, Plan Hash: -993736942, Minimum Cost Plan Hash: -1873216041 (14 rows)

パーティションごとにアクセス方法が異なる別の承認済みプランを考えてみましょう。

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Bitmap Heap Scan on tbl_a3 tbl_a_3 Recheck Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Bitmap Index Scan on tbl_a3_i_idx Index Cond: ((i >= 990) AND (i <= 2100)) SQL Hash: 1553185667, Plan Hash: 2032136998 (12 rows)

この場合、2 つのパーティションからデータを読み込むプランは適用されません。承認されたプランの(アクセス方法、インデックス名)の組み合わせがすべて使用可能でない限り、プランを実施することはできません。例えば、以下のプランはプランのハッシュが異なり、承認されたプランはこのような場合には適用できません。

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1900 and j < 9910 and k > 50; QUERY PLAN ------------------------------------------------------------------------- Append -> Bitmap Heap Scan on tbl_a1 tbl_a_1 Recheck Cond: ((i >= 990) AND (i <= 1900)) Filter: ((j < 9910) AND (k > 50)) -> Bitmap Index Scan on tbl_a1_i_idx Index Cond: ((i >= 990) AND (i <= 1900)) -> Bitmap Heap Scan on tbl_a2 tbl_a_2 Recheck Cond: ((i >= 990) AND (i <= 1900)) Filter: ((j < 9910) AND (k > 50)) -> Bitmap Index Scan on tbl_a2_i_idx Index Cond: ((i >= 990) AND (i <= 1900)) Note: This is not an Approved plan. No usable Approved plan was found. SQL Hash: 1553185667, Plan Hash: -568647260 (13 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1900 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 1900)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 1900) AND (j < 9910) AND (k > 50)) Note: This is not an Approved plan. No usable Approved plan was found. SQL Hash: 1553185667, Plan Hash: -496793743 (8 rows)

命名規則

QPM が宣言的パーティションテーブルでプランを適用するには、親テーブル、テーブルパーティション、インデックスに固有の命名規則に従う必要があります。

  • 親テーブル名 - これらの名前は、数字だけでなく、アルファベットまたは特殊文字が異なっていなければなりません。例えば、tA、tB、tC は個別の親テーブルには使用できる名前ですが、t1、t2、t3 はそうではありません。

  • 各パーティションテーブル名 - 同じ親を持つパーティション名は、数字のみが異なっている必要があります。例えば、tA に指定できるパーティション名は tA1、tA2、t1a、t2A、または複数桁の場合もあります。

    その他の違い (文字、特殊文字) があっても、プランの適用は保証されません。

  • インデックス名 – パーティションテーブル階層で、すべてのインデックスに一意の名前があることを確認します。つまり、名前の数値以外の部分は異なっている必要があります。例えば、tA_col1_idx1 という名前のインデックスを持つ tA という名前のパーティションテーブルがある場合、tA_col1_idx2 という名前の別のインデックスを使用することはできません。ただし、tA_a_col1_idx2 というインデックスは、数値以外の部分が一意であるため使用できます。このルールは、親テーブルと個々のパーティションテーブルの両方で作成されたインデックスに適用されます。

上記の命名規則に従わないと、承認されたプランの実施に失敗する可能性があります。次の例は、このような実施が失敗したことを示しています。

postgres=>create table t1(i int, j int, k int, l int, m int) partition by range(i); CREATE TABLE postgres=>create table t1a partition of t1 for values from (0) to (1000); CREATE TABLE postgres=>create table t1b partition of t1 for values from (1001) to (2000); CREATE TABLE postgres=>SET apg_plan_mgmt.capture_plan_baselines TO 'manual'; SET postgres=>explain (hashes true, costs false) select count(*) from t1 where i > 0; QUERY PLAN -------------------------------------------------------------------------- Aggregate -> Append -> Seq Scan on t1a t1_1 Filter: (i > 0) -> Seq Scan on t1b t1_2 Filter: (i > 0) SQL Hash: -1720232281, Plan Hash: -1010664377 (7 rows)
postgres=>SET apg_plan_mgmt.use_plan_baselines TO 'on'; SET postgres=>explain (hashes true, costs false) select count(*) from t1 where i > 1000; QUERY PLAN ------------------------------------------------------------------------- Aggregate -> Seq Scan on t1b t1 Filter: (i > 1000) Note: This is not an Approved plan. No usable Approved plan was found. SQL Hash: -1720232281, Plan Hash: 335531806 (5 rows)

2 つのプランは同じように見えますが、子テーブルの名前によって Plan Hash 値は異なります。数値のみでなくアルファベット文字で名前が異なるテーブルでは、プランの実施が失敗します。