パーティショニングは、大規模なテーブルまたはインデックスを、物理的に小さく分割し、個別に管理可能な単位(パーティション)に分ける手法です。各パーティションには独自の名前とストレージ属性がありますが、親テーブルと同じ論理構造(列名、データの型、制約など)を共有します。アプリケーションはこの分割を認識せず、既存のクエリおよび DML ステートメントは変更なしで動作します。
テーブルをパーティション化するタイミング
以下の状況でテーブルをパーティション化することを推奨します:
テーブルサイズが物理メモリを超える場合。 テーブルのサイズがデータベースサーバーの物理メモリを超えると、パーティショニングによりクエリパフォーマンスが大幅に向上します。一般的な目安として、2 GB を超えるテーブルはパーティション化することを推奨します。
テーブルにアクティブなデータと既存データが混在する場合。 最新の月のデータは書き込み可能なパーティションに格納し、それより古い月のデータは読み取り専用のパーティションに格納します。このパターンにより、大量データの管理が高速かつ安全になります。
メリット
高いパフォーマンス
パーティショニングは、パーティション・プルーニング対応のクエリにおいて、インデックスツリーの上位層を置き換えます。クエリが特定の 1 つまたは複数のパーティションを対象とする場合、データベースは全インデックスを走査するのではなく、該当パーティションのみを逐次スキャンします。散在したレコードではなく隣接したデータチャンクを処理することで、速度と管理性の両方が向上します。
容易な管理
パーティションは独立したオブジェクトです。DDL 操作は、単一のパーティション、全体のテーブル、または任意のインデックスを対象に実行できます。これにより、インデックス再構築などのリソースを多く消費するタスクを、パーティション単位で段階的に実行できます。大量の行を削除する場合は、DROP TABLE でパーティションを削除するか、ALTER TABLE DETACH PARTITION でデタッチします。いずれの操作も、大量の DELETE よりもはるかに高速であり、大量削除によって発生する VACUUM のオーバーヘッドを回避できます。
リソース競合の低減
OLTP ワークロードでは、DML 操作を特定のパーティションに隔離することで、テーブル全体におけるロック競合を低減できます。
高い可用性
パーティションの 1 つが利用不可になった場合でも、テーブルの残りの部分は引き続きアクセス可能です。クエリ オプテマイザーは自動的に利用不可のパーティションをクエリプランから除外するため、影響を受けないパーティションは通常通りクエリに応答します。
低いストレージコスト
アクセス頻度の低いパーティションを、低速で安価なストレージに移動することで、データを保持したままコストを削減できます。
パーティショニングは、テーブルが実際に大規模である場合にのみ効果を発揮します。テーブルサイズがデータベースサーバーの物理メモリに達した時点でパーティション化することを推奨します。
仕組み
このセクションでは、パーティションキー、パーティショニング戦略、およびマルチレベルパーティショニングの 3 つの概念について説明します。これらは、行が各パーティションにどのように分散されるかを決定する要素です。
パーティションキー
パーティションキーは、単一の列または複数の列の組み合わせです。PolarDB for PostgreSQL (Compatible with Oracle) では、このパーティションキーを用いて、各 INSERT、UPDATE、DELETE 操作を自動的に適切なパーティションにルーティングします。
以下のレンジパーティショニングの例では、logdate がパーティションキーです。各月ごとのパーティションには、その定義された範囲内に logdate の値を持つ行が格納されます。
例 1
CREATE TABLE measurement (
city_id int not null,
logdate date not null,
peaktemp int,
unitsales int
) PARTITION BY RANGE (logdate);
CREATE TABLE measurement_y2006m02 PARTITION OF measurement
FOR VALUES FROM ('2006-02-01') TO ('2006-03-01');
CREATE TABLE measurement_y2006m03 PARTITION OF measurement
FOR VALUES FROM ('2006-03-01') TO ('2006-04-01');
...
CREATE TABLE measurement_y2007m11 PARTITION OF measurement
FOR VALUES FROM ('2007-11-01') TO ('2007-12-01');
CREATE TABLE measurement_y2007m12 PARTITION OF measurement
FOR VALUES FROM ('2007-12-01') TO ('2008-01-01')
TABLESPACE fasttablespace;
CREATE TABLE measurement_y2008m01 PARTITION OF measurement
FOR VALUES FROM ('2008-01-01') TO ('2008-02-01')
WITH (parallel_workers = 4)
TABLESPACE fasttablespace;パーティショニング戦略
PolarDB for PostgreSQL (Compatible with Oracle) では、3 種類のパーティショニング戦略がサポートされています。
レンジパーティショニング
パーティションキーの値の範囲(日付や数値識別子など)に基づいて行を分散します。各パーティションには非包含の上限値があり、値 10 はパーティション [10, 20) に属し、[1, 10) には属しません。
例 1 の measurement テーブルは、レンジパーティショニングを使用しています。
PolarDB では、レンジパーティショニングの拡張であるインターバル・レンジパーティショニングもサポートしています。詳細については、「インターバル・レンジパーティショニング」をご参照ください。
リストパーティショニング
パーティションキーの値の明示的なリストに基づいて行を分散します。各パーティションには、その定義されたリストに含まれるキー値を持つ行のみが格納されます。
例 2
CREATE TABLE department(deptno INT4 Primary Key,dname VARCHAR(50), location VARCHAR(100)) PARTITION BY LIST (deptno);
CREATE TABLE department_p1 partition of department for values in (10, 20);
CREATE TABLE department_p1 partition of department for values in (30, 40);この例では、department_p1 には deptno が 10 または 20 の行が格納され、department_p2 には deptno が 30 または 40 の行が格納されます。
ハッシュパーティショニング
パーティションキーのハッシュ値に基づいて行を分散します。各パーティションには、hash(key) % modulus = remainder を満たす行が格納されます。
例 3
create table idxpart (i int) partition by hash (i);
create table idxpart0 partition of idxpart for values with (modulus 2, remainder 0);
create table idxpart1 partition of idxpart for values with (modulus 2, remainder 1);idxpart0 には、i のハッシュ値を 2 で割った余りが 0 の行が格納され、idxpart1 には余りが 1 の行が格納されます。
マルチレベルパーティショニング
マルチレベルパーティショニングでは、パーティションをネストしてサブパーティションを作成し、さらにサブパーティションをパーティション化できます。各レベルで異なる戦略を適用可能であり、たとえば第 1 レベルでレンジ、第 2 レベルでハッシュ、第 3 レベルでリストを採用できます。
PolarDB では、無制限のパーティショニングレベルがサポートされていますが、階層は 3 レベル以内に抑えることを推奨します。それ以上の深さは管理の複雑性を高め、クエリパフォーマンスの低下を招く可能性があります。
例 4
CREATE TABLE measurement (
city_id int not null,
logdate date not null,
peaktemp int,
unitsales int
) PARTITION BY RANGE (logdate);
CREATE TABLE measurement_y2006m03 PARTITION OF measurement
FOR VALUES FROM ('2006-03-01') TO ('2006-04-01') PARTITION BY Hash (city_id);
CREATE TABLE measurement_y2006m03_hash1 PARTITION OF measurement_y2006m03
for values with (modulus 2, remainder 0) PARTITION BY List (peaktemp);
CREATE TABLE measurement_y2006m03_hash1_l1 PARTITION OF measurement_y2006m03_hash1 for values in (10, 20);次のステップ
パーティションの作成、追加、マージ、分割、削除を行うコマンドの完全な一覧については、「パーティションテーブル向けコマンド一覧」をご参照ください。