AnalyticDB for PostgreSQLを使用すると、大きなテーブルをパーティションに分割できます。 条件を使用してデータをクエリすると、システムは指定された条件を満たすパーティションのみをスキャンします。 これにより、テーブル全体のスキャンが防止され、クエリのパフォーマンスが向上します。
サポートされているパーティション分割タイプ
範囲分割: データは、日付などの数値範囲に基づいて分割されます。
リストパーティショニング: データは、都市属性などの値のリストに基づいて分割されます。
マルチレベル分割: データは数値範囲と値のリストに基づいて分割されます。
範囲パーティション分割テーブルの作成
AnalyticDB for PostgreSQLでは、START値、END値、および範囲内の間隔を定義するEVERY句を指定することで、パーティションを自動的に生成できます。 デフォルトでは、START値は包括的で、END値は排他的です。
日付で範囲分割されたテーブルを作成します。 例:
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') );
数値で範囲分割されたテーブルを作成します。 たとえば、INTデータ型の列をパーティションキーとして使用できます。 例:
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 );
リスト分割テーブルの作成
リストパーティションテーブルを作成するときは、値の比較が可能なデータ型を持つ任意の列にパーティションキーを設定できます。また、パーティションキーの指定された値ごとに説明を宣言する必要があります。
リスト分割テーブルを作成します。 例:
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 );
マルチレベルパーティションテーブルの作成
AnalyticDB for PostgreSQLでは、マルチレベルパーティションを持つテーブルを作成できます。 次の例は、3レベルのパーティションテーブルを作成する方法を示しています。 レベル1パーティションのデータは年ごとに範囲分割され、レベル2パーティションのデータは月ごとに範囲分割され、レベル3パーティションのデータは地域ごとにリスト分割されます。 レベル2およびレベル3のパーティションは、サブパーティションと呼ばれます。
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ステートメントを実行して、パーティションをパーティションテーブルに追加できます。 パーティション分割テーブルの作成時にサブパーティションテンプレートが使用されている場合、追加されたパーティションもそれに応じてサブパーティション分割されます。 次の例は、パーティションを追加する方法を示しています。
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ステートメントを使用して、既存のパーティションをサブパーティション化することもできます。 例:
ALTER TABLE sales ALTER PARTITION FOR (RANK(12))
ADD PARTITION africa VALUES ('africa');
デフォルトのパーティションを持つパーティションテーブルにパーティションを追加することはできません。 このようなパーティションテーブルにパーティションを追加するには、デフォルトのパーティションを分割します。 詳細については、このトピックの「パーティションの分割」セクションをご参照ください。
子パーティションテーブルの名前を指定する
パーティションテーブルを作成するときに、WITH(tablename=<tablename_1>)
句を使用して、AnalyticDB for PostgreSQL V6.3.10.9の子パーティションテーブルの名前を指定できます。
サンプル文:
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')
);
パーティションを分割する
ALTER TABLEステートメントを実行して、パーティションを2つのパーティションに分割できます。 パーティション分割には、次の制限があります。
サブパーティションが存在する場合、下位レベルのサブパーティションのみを分割できます。
パーティション分割ステートメントのAT句で指定された分割値は、2番目のパーティションに割り当てられます。
たとえば、1月2017日のデータを含むパーティションが2つのパーティションに分割されているとします。 第1のパーティションは1月1日から1月15日までのデータを含み、第2のパーティションは1月16日から1月31日までのデータを含む。 例:
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);
パーティションの粒度を決定する
パーティションテーブルを使用する場合、パーティションの粒度を決定する必要があります。 たとえば、テーブルを時間でパーティション分割するには、日、週、または月の粒度を選択できます。 より細かい粒度は、各パーティションにおいてより少ないデータをもたらすが、より多くのパーティションをもたらす。 パーティションの数は絶対標準では測定されません。 各テーブルに200個以下のパーティションを割り当てることを推奨します。 パーティションの数が多いと、データベースのパフォーマンスが低下する場合があります。 たとえば、クエリオプティマイザが実行計画を生成するのに時間がかかるか、VACUUM操作が完了するのに時間がかかります。
パーティション分割テーブルクエリの最適化
AnalyticDB for PostgreSQLは、パーティションテーブルのパーティションプルーニングをサポートして、クエリパフォーマンスを向上させます。 パーティションプルーニングが有効になっている場合、システムはテーブル全体をスキャンするのではなく、クエリ条件に基づいて必要なパーティションのみをスキャンします。 例:
EXPLAIN
SELECT * FROM sales
WHERE year = 2008
AND month = 1
AND day = 3
AND region = 'usa';
上記の例では、クエリ条件は、レベル1パーティション2008のレベル2パーティション1のレベル3パーティションusaにあります。 したがって、レベル3パーティションusa内のデータのみがクエリ中にスキャンされる。 次の実行計画では、468レベル3パーティションの1つだけをスキャンする必要があることを示しています。
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
パーティション定義の照会
次のSQL文を実行して、テーブル内のすべてのパーティションの定義を照会できます。
SELECT
partitionboundary,
partitiontablename,
partitionname,
partitionlevel,
partitionrank
FROM pg_partitions
WHERE tablename='sales';
パーティション分割テーブルの維持
パーティションテーブルでパーティションを管理できます。 たとえば、パーティションの追加、削除、名前変更、切り捨て、交換、および分割を行うことができます。 詳細については、「大きなテーブルのパーティション化」をご参照ください。
子パーティション分割テーブルの名前変更
子パーティションテーブルの名前は、AnalyticDB for PostgreSQL V6.3.10.9で変更できます。
子パーティションテーブルの名前をpartition_with_name_list_p1
からpartition_with_name_list_p1r
に変更するためのサンプルステートメント:
ALTER TABLE partition_with_name_list_p1 RENAME TO partition_with_name_list_p1r;
よくある質問
Q: テーブルのパーティションキーを指定するにはどうすればよいですか?
A: テーブルに主キーがある場合は、主キー列をパーティションキーとして指定する必要があります。 テーブルに主キーがない場合は、任意の列をパーティションキーとして指定できます。