AnalyticDB for PostgreSQL では、大規模なテーブルを複数のパーティションに分割できます。これにより、クエリはフィルター条件に一致するパーティションのみをスキャンし、全表スキャンを回避してクエリパフォーマンスを向上させます。
パーティション化を利用するタイミング
以下の 3 つの条件がすべて満たされる場合に、パーティション化の効果が最も高まります。
テーブルが大規模であること。 行数が非常に多いテーブルは、パーティション化の対象として適しています。
クエリパフォーマンスが不十分であること。 クエリの応答時間が許容範囲を超えて遅くなる場合にのみ、パーティション化を適用します。
クエリの述語に明確なアクセスパターンがあること。 一般的なクエリの
WHERE句を確認してください。同じ列が繰り返し出現する場合、その列は自然なパーティションキー候補となります。
サポートされるパーティション化タイプ
| タイプ | データの分割方法 | 典型的な利用シーン |
|---|---|---|
| 範囲パーティション化 | 日付や整数などの数値範囲 | 時系列データ、連番 ID |
| リストパーティション化 | 値の明示的なリスト | カテゴリデータ(例:リージョン、ステータス) |
| 多段パーティション化 | 複数のレベルで範囲パーティション化とリストパーティション化を組み合わせた方式 | 複数のフィルターディメンションを持つ大規模データセット |
パーティションキーの選択
パーティションキーは、パーティションプルーニングが有効に機能するかどうかを決定します。
クエリの述語と一致すること。
WHERE句に最も頻繁に出現する列または列群を選択します。パーティションプルーニングは、クエリ条件にパーティションキーが含まれる場合にのみ有効です。データ保持戦略と整合性を保つこと。 旧データを定期的に一括削除する場合は、削除対象のデータが単一のパーティションに収まるようにパーティションを設計します。DELETE 文を実行するよりも、パーティションを削除(
DROP PARTITION)する方がはるかに高速です。プライマリキー制約への準拠。 テーブルにプライマリキーが定義されている場合、パーティションキーは必ずプライマリキー列のいずれかでなければなりません。プライマリキーが未定義の場合は、任意の列をパーティションキーとして指定できます。
範囲パーティション化テーブルの作成
START、END、EVERY を指定することで、指定範囲内のパーティションを自動生成できます。START はデフォルトで包含(inclusive)、END は排他(exclusive)です。
日付によるパーティション化:
CREATE TABLE sales (id int, date date, amt decimal(10,2))
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
( START (date '2016-01-01') INCLUSIVE
END (date '2017-01-01') EXCLUSIVE
EVERY (INTERVAL '1 day') );整数によるパーティション化(デフォルトパーティションあり):
CREATE TABLE rank (id int, rank int, year int, gender char(1), count int)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
( START (2006) END (2016) EVERY (1),
DEFAULT PARTITION extra );DEFAULT PARTITION は、定義済みのすべての範囲外に該当する行をキャッチします。リストパーティション化テーブルの作成
パーティションキーには、値比較をサポートするデータの型を持つ任意の列を指定できます。各パーティションに対して値の説明を宣言します。
CREATE TABLE rank (id int, rank int, year int, gender
char(1), count int )
DISTRIBUTED BY (id)
PARTITION BY LIST (gender)
( PARTITION girls VALUES ('F'),
PARTITION boys VALUES ('M'),
DEFAULT PARTITION other );多段パーティション化テーブルの作成
以下の例では、3 段階のパーティション化テーブルを作成します。
第 1 段階:
year列による範囲パーティション化第 2 段階(サブパーティション):
month列による範囲パーティション化第 3 段階(サブパーティション):
region列によるリストパーティション化
CREATE TABLE sales (id int, year int, month int, day int,
region text)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
SUBPARTITION BY RANGE (month)
SUBPARTITION TEMPLATE (
START (1) END (13) EVERY (1),
DEFAULT SUBPARTITION other_months )
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE (
SUBPARTITION usa VALUES ('usa'),
SUBPARTITION europe VALUES ('europe'),
SUBPARTITION asia VALUES ('asia'),
DEFAULT SUBPARTITION other_regions )
( START (2002) END (2012) EVERY (1),
DEFAULT PARTITION outlying_years );パーティションの追加
既存のパーティションテーブルにパーティションを追加するには、ALTER TABLE ... ADD PARTITION を使用します。
テーブルがサブパーティショントレムプレートを使用して作成された場合、新規パーティションは自動的にサブパーティション化されます。
ALTER TABLE sales ADD PARTITION
START (date '2017-02-01') INCLUSIVE
END (date '2017-03-01') EXCLUSIVE;サブパーティショントレムプレートが使用されていない場合は、パーティション追加時にインラインでサブパーティションを定義します。
ALTER TABLE sales ADD PARTITION
START (date '2017-02-01') INCLUSIVE
END (date '2017-03-01') EXCLUSIVE
( SUBPARTITION usa VALUES ('usa'),
SUBPARTITION asia VALUES ('asia'),
SUBPARTITION europe VALUES ('europe') );既存のパーティションをサブパーティション化するには、以下のように記述します。
ALTER TABLE sales ALTER PARTITION FOR (RANK(12))
ADD PARTITION africa VALUES ('africa');デフォルトパーティションが定義されたテーブルには、パーティションを直接追加できません。このようなテーブルにパーティションを追加するには、代わりにデフォルトパーティションを分割します。「パーティションの分割」をご参照ください。
パーティション名の指定
AnalyticDB for PostgreSQL V6.3.10.9 以降では、テーブル作成時に WITH(tablename=<tablename>) 句を使用して、パーティションに明示的な名前を割り当てることができます。
CREATE TABLE partition_with_name_list (a int, b int, c int) DISTRIBUTED BY (a) PARTITION BY LIST (a)
(
PARTITION p1 VALUES (1) WITH (tablename='partition_with_name_list_p1'),
PARTITION p2 VALUES (2) WITH (tablename='partition_with_name_list_p2'),
PARTITION p3 VALUES (3) WITH (tablename='partition_with_name_list_p3'),
PARTITION p4 VALUES (4) WITH (tablename='partition_with_name_list_p4')
);パーティションの名前の変更
AnalyticDB for PostgreSQL V6.3.10.9 以降では、以下のコマンドでパーティションの名前を変更できます。
ALTER TABLE partition_with_name_list_p1 RENAME TO partition_with_name_list_p1r;パーティションの分割
ALTER TABLE ... SPLIT PARTITION を使用すると、1 つのパーティションを 2 つに分割できます。
使用制限:
サブパーティションが存在する場合、分割可能なのは最下位レベルのサブパーティションのみです。
AT句で指定した分割値は、2 番目のパーティションに割り当てられます。
既存パーティションの分割:
以下の例では、2017 年 1 月のパーティションを 1 月 16 日で分割します。1 月 1 日~15 日のデータは最初のパーティションに、1 月 16 日~31 日のデータは 2 番目のパーティションに格納されます。
ALTER TABLE sales SPLIT PARTITION FOR ('2017-01-01')
AT ('2017-01-16')
INTO (PARTITION jan171to15, PARTITION jan1716to31);デフォルトパーティションの分割による新規パーティションの追加:
テーブルにデフォルトパーティションが定義されている場合、それを分割して名前付きパーティションを作成できます。INTO 句では、デフォルトパーティションを 2 番目に指定する必要があります。
ALTER TABLE sales SPLIT DEFAULT PARTITION
START ('2017-01-01') INCLUSIVE
END ('2017-02-01') EXCLUSIVE
INTO (PARTITION jan17, default partition);パーティション粒度の決定
パーティション粒度は、「各パーティションに格納されるデータ量」と「パーティション総数」のトレードオフを伴います。粒度を細かくすると、各パーティションのデータ量は減少しますが、パーティション総数は増加します。
一般的なガイドラインとして、**1 つのテーブルあたりパーティション数を 200 個以下**に保つことを推奨します。パーティション数が過剰になると、データベースパフォーマンスが低下する可能性があります。例えば、クエリ オプティマイザーが実行計画を生成するのに時間がかかるようになり、VACUUM 操作の完了にもより長い時間がかかるようになります。
パーティションテーブルのクエリ最適化
AnalyticDB for PostgreSQL ではパーティションプルーニングをサポートしています。クエリにパーティションキーに対する条件が含まれている場合、オプティマイザーは全テーブルではなく、条件に一致するパーティションのみをスキャンします。
プルーニングが有効であることを確認する:
EXPLAIN
SELECT * FROM sales
WHERE year = 2008
AND month = 1
AND day = 3
AND region = 'usa';期待される出力(プルーニングが正常に動作している場合):
Gather Motion 4:1 (slice1; segments: 4) (cost=0.00..431.00 rows=1 width=24)
-> Sequence (cost=0.00..431.00 rows=1 width=24)
-> Partition Selector for sales (dynamic scan id: 1) (cost=10.00..100.00 rows=25 width=4)
Filter: year = 2008 AND month = 1 AND region = 'usa'::text
Partitions selected: 1 (out of 468)
-> Dynamic Table Scan on sales (dynamic scan id: 1) (cost=0.00..431.00 rows=1 width=24)
Filter: year = 2008 AND month = 1 AND day = 3 AND region = 'usa'::textこの実行計画において、Partitions selected: 1 (out of 468) という表示は、プルーニングが有効に機能していることを確認できます。特定のフィルター条件を指定しているにもかかわらず、選択されるパーティション数が非常に多い場合は、フィルター対象の列がパーティションキーと一致しているかを確認してください。
クエリ パーティション定義
テーブル内のすべてのパーティションを照会するには、pg_partitions システムビューをクエリします。
SELECT
partitionboundary,
partitiontablename,
partitionname,
partitionlevel,
partitionrank
FROM pg_partitions
WHERE tablename='sales';関連操作
パーティションの削除、切り捨て(TRUNCATE)、交換(EXCHANGE)など、パーティション管理に関するすべての操作の一覧については、「大規模テーブルのパーティション化」をご参照ください。
よくある質問
パーティションキーはどのように選べばよいですか?
テーブルにプライマリキーが定義されている場合、パーティションキーは必ずプライマリキー列のいずれかでなければなりません。プライマリキーが未定義の場合は、任意の列をパーティションキーとして指定できます。パーティションプルーニングの効果を最大限に発揮するには、WHERE 句に最も頻繁に出現する列を選択してください。