テーブルパーティショニングの内部とパーティションプルーニング
巨大表でも、述語に合うパーティションだけを読めば走査量は桁で減ります。レンジ・リスト・ハッシュの物理分割と、プルーニング・パーティションワイズ結合が効く条件を原理から押さえられます。
- 1.パーティショニングは1論理表を境界メタデータで複数の物理子表に分け、各子表を独立した格納・索引単位として持つ。レンジは境界値の順序、リストは値の集合、ハッシュは剰余で行の所属を決める。
- 2.パーティションプルーニングは、述語とパーティション境界を突き合わせてアクセス対象の子表を計画段階で絞る最適化。定数で決まる静的プルーニングと、束縛値や結合キーが実行時に分かってから絞る動的プルーニングがある。
- 3.両表が同じキーで同じ境界に分割されていれば、対応するパーティション同士だけを結合するパーティションワイズ結合が成り立ち、結合の入力をパーティション単位に小さく分割できる。
パーティションは「分けて読まない」ための仕組み
パーティショニング の本質は、表を小さくすることではなく、読まなくてよい部分を計画段階で確定できる構造を作ることです。1つの論理表を境界の定義(メタデータ)に従って複数の物理的な子表(パーティション)へ分け、各子表は独立した格納領域とローカル索引を持ちます。クエリの述語がパーティションキーに掛かると、オプティマイザは境界と述語を突き合わせ、合致し得ない子表を走査計画から丸ごと外します。これがパーティションプルーニング(partition pruning、枝刈り) で、全表走査を「関係するパーティションの走査」に縮める原理です。
3つの物理分割:所属を決める関数
行がどのパーティションに入るかは、パーティションキーの値からパーティションを決める写像で決まります。方式ごとにこの写像が違い、それがプルーニングの効き方を左右します。
| 方式 | 所属の決め方 | 境界メタデータ | 強い述語 |
|---|---|---|---|
| レンジ | キーが属する値域を順序で判定 | 各パーティションの下限・上限(区間) | 範囲条件・等値(BETWEEN, >=, =) |
| リスト | キー値が属する値集合を判定 | パーティションごとの許容値の集合 | 等値・IN(離散カテゴリ) |
| ハッシュ | hash(key) mod N でスロットを決定 | モジュラス N と各パーティションの剰余 | 等値のみ(範囲は全体に散る) |
レンジは境界が順序付き区間なので、created_at >= '2026-06-01' のような範囲述語と相性が良く、区間と述語の重なりだけを残せます。リストは region IN ('JP','KR') のような離散値の振り分けに向きます。ハッシュは hash(key) mod N で行を均し、件数を平準化してホットスポットを避けますが、剰余は値の順序を壊すため範囲述語ではプルーニングが効かず、等値述語でのみ単一スロットに絞れます。レンジ・リスト・ハッシュという同じ三分法は、サーバーをまたぐ分散でも現れます(→ シャーディング方式)。
-- ハッシュ:剰余で4分割。等値なら1パーティションに絞れるが範囲は4つ全部に散る
CREATE TABLE events (id bigint, user_id bigint, ts timestamptz)
PARTITION BY HASH (user_id);
CREATE TABLE events_p0 PARTITION OF events
FOR VALUES WITH (MODULUS 4, REMAINDER 0);
-- ... p1..p3 まで REMAINDER 1,2,3
静的プルーニング:計画時に定数で絞る
述語がコンパイル時に定数へ評価できる場合、オプティマイザは実行前にアクセス対象を確定できます。これが静的プルーニングです。手順は単純で、述語をパーティションキーの制約式へ正規化し、各パーティションの境界制約と論理的に矛盾するものを除外します。
パーティション境界(レンジ・月分割)
p_2026_05: [2026-05-01, 2026-06-01)
p_2026_06: [2026-06-01, 2026-07-01)
p_2026_07: [2026-07-01, 2026-08-01)
述語: created_at >= '2026-06-15'
p_2026_05 … 上限 06-01 が 06-15 未満 → 矛盾 → 除外
p_2026_06 … 区間が 06-15 以降を含み得る → 残す
p_2026_07 … 全域が 06-15 以降 → 残す
→ 走査は p_2026_06, p_2026_07 のみ
これは 述語プッシュダウン の最も粗い粒度の適用で、ファイル単位・パーティション単位に効きます。さらに細かい粒度では、各パーティション内のブロックの min/max 統計でブロックを飛ばす段が続きます。粒度はパーティション → 行グループ → ブロックと段階的に効き、プルーニングはその最上段に位置づけられます。
プルーニングは述語をパーティション境界の制約と照合できて初めて成立します。WHERE created_at >= '2026-06-15' は効きますが、WHERE date_trunc('month', created_at) = '2026-06-01' のようにキー列を関数で包むと、多くのエンジンは境界と突き合わせられず全パーティションを走査します。型の暗黙変換(文字列とタイムスタンプの比較など)でも同じく照合に失敗することがあります。プルーニングを活かす要点は、述語をパーティションキー列そのものへの単純比較として書くことです。
動的プルーニング:実行時に値が分かってから絞る
述語の値が計画時に未知でも、実行が始まれば確定するケースがあります。代表は、束縛変数(プリペアドステートメントのパラメータ)と、結合相手から流れてくる結合キーです。これらを実行時に評価して初めてパーティションを絞るのが動的プルーニングです。
- パラメータ由来:
WHERE region = ?のプランは、計画時にはどのリストパーティションに当たるか不明です。エンジンは「実行時に?を評価してから対象パーティションを選ぶ」プラン(実行時プルーニング)を作ります。これはプラン再利用と相性が問題になりやすく、束縛値ごとに当たるパーティションが変わるため、固定プランの妥当性が値で揺れます(→ パラメータスニッフィング)。 - 結合由来:ハッシュ結合などで、ビルド側(小さい表)を走査して得た結合キーの実値の集合を使い、プローブ側のパーティション付き大表から不要なパーティションを実行時に外す方式です。ビルド側に存在しないキーのパーティションは、最初から走査しません。
動的プルーニングの利得は、対象を絞った結果としてそのパーティションを開かずに済む点にあります。したがって絞り込みの判断は、当該パーティションの走査を起動する前に完了していなければなりません。実装上はビルド側を先に完了させ、得たキー集合(または min/max)でプローブ側のパーティション選択を駆動します。読み始めてから捨てるだけでは I/O は減らず、プルーニングとは呼べません。
パーティションワイズ結合:分けたまま結合する
両方の表が同じキー・同じ境界で分割されていれば、結合は「全体 ⋈ 全体」ではなく「対応パーティション同士の結合の和」に分解できます。これがパーティションワイズ結合(partition-wise join) です。境界が一致するため、あるパーティションの行が結合相手になり得るのは、相手表の同じ境界のパーティションだけだからです。
R を [a,b),[b,c),[c,d) に分割、S も同一境界で分割
通常: R ⋈ S (全行が結合候補)
分割後: (R1 ⋈ S1) ∪ (R2 ⋈ S2) ∪ (R3 ⋈ S3)
→ R1 の行は S2,S3 とは決して一致しない(境界が交わらない)ため照合不要
利点は2つあります。第一に、各結合の入力が小さくなるため、ハッシュ結合のハッシュ表がパーティション単位で済み、メモリに収まりやすく外部化(あふれ)を避けられます。第二に、パーティション単位の結合は互いに独立なので、並列実行の自然な単位になります。分散環境では、結合キーで両表が同じノードへ配置(コロケート)されていれば、ネットワーク越しの行移動なしに各ノードで局所結合でき、これはパーティションワイズ結合の分散版です(→ 分散結合とシャッフル)。
両表が同一境界で分かれている完全なパーティションワイズ結合が理想ですが、片方だけがパーティション化されている場合でも、もう一方を結合キーで動的に再分配して境界を揃える部分パーティションワイズ結合が使えるエンジンがあります。完全一致ほどの効果はないものの、結合を分割して並列化・メモリ削減の恩恵を一部得られます。
パーティショニングは境界メタデータ+独立した物理子表であり、行の所属はレンジ=順序付き区間、リスト=値集合、ハッシュ=hash(key) mod N で決まる、と即答できるように。プルーニングは述語と境界の照合でアクセス対象を絞ること、静的=計画時の定数/動的=実行時の束縛値・結合キーの2種がある、と区別を。ハッシュは範囲述語では効かず等値のみ、キーを関数で包むと照合不能で止まる、まで押さえると確実。パーティションワイズ結合は同一キー・同一境界が条件です。
まとめ
パーティショニングは1論理表を境界メタデータに従って独立した物理子表へ分ける構造で、行の所属はレンジ(順序付き区間)・リスト(値集合)・ハッシュ(hash(key) mod N)で決まります。パーティションプルーニングは述語とパーティション境界を照合してアクセス対象の子表を絞る最適化で、定数で確定する静的プルーニングと、束縛値や結合キーが実行時に分かってから絞る動的プルーニングがあります。ハッシュは剰余が順序を壊すため範囲述語では効かず等値のみ、キーを関数で包むと境界照合に失敗して全走査に戻る点が落とし穴です。両表が同一キー・同一境界で分かれていれば、対応パーティション同士だけを結合するパーティションワイズ結合が成り立ち、結合入力の縮小・メモリ削減・並列化と、分散環境でのコロケート結合(ネットワーク転送ゼロ)につながります。EXPLAIN にパーティション数の絞り込みや実行時プルーニングが現れるかが、効いているかの直接の指標です。
データベース Article
テーブルパーティショニングの内部とパーティションプルーニングを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
パーティショニング
比較で見る軸
難易度: advanced / カテゴリ: データベース / タグ数: 5
導入後に効く点
パーティションプルーニングは、述語とパーティション境界を突き合わせてアクセス対象の子表を計画段階で絞る最適化。定数で決まる静的プルーニングと、束縛値や結合キーが実行時に分かってから絞る動的プルーニングがある。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- データベース
- タグ数
- 5
判断チェックリスト
- 自社の用途が「パーティショニング / パーティションプルーニング」に近いか確認する。
- 強みである「パーティショニングは1論理表を境界メタデータで複数の物理子表に分け、各子表を独立した格納・索引単位として持つ。レンジは境界値の順序、リストは値の集合、ハッシュは剰余で行の所属を決める。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。