パーティショニングとは?RANGE・LIST・HASHの使い分けと絞り込み設計を実装者目線で解説【2026年版】
1つの表を分割キーで区切り、アプリケーションからは1つの表のまま扱い続ける仕組みがパーティショニングです。効果の有無は、検索条件に分割キーが乗るか、古いデータを期間単位で捨てる運用があるかでほぼ決まります。この記事では、シャーディングやディスク領域の分割との線引き、RANGE・LIST・HASHの三方式と分割キーの選び方、絞り込み(プルーニング)が効かないクエリの見つけ方、一意キーや外部キーへ波及する制約、区画を止めずに付け外しする運用要件を実装者目線で整理し、最後に採用の線引きと見送る条件を明示します。
まとめ:パーティショニングで効果が出る条件と無駄になる条件の要点
結論から示します。パーティショニングが投資に見合うのは、次の3条件がそろったときです。第一に、主要なクエリのWHERE句へ分割キーが必ず乗ること。第二に、保存期間が決まっていて古いデータを期間単位で切り離す運用があること。第三に、単一表が数億行またはインデックスがメモリに収まらない規模へ達していること。欠けたまま導入すると、区画の数だけ管理対象が増えて終わります。
逆に見送るべき場面もはっきりしています。検索条件が分割キー以外に散る設計、分割キーを含まない一意制約が必要な表、外部キーで他表と結ばれたInnoDBの表。いずれも制約側が先に壁になります。数千万行の規模なら、まずインデックスの見直しと保存期間の短縮で足ります。
速度の手段ではなく、運用単位を作る手段として捉えると判断を誤りません。区画ごとに切り離せる、区画ごとに古いものを落とせる。この粒度こそが本体の価値で、検索の絞り込みは副産物という位置づけになります。
単一データベース内で表を切り分けるパーティショニングの定義と適用範囲
まず対象範囲を確定させます。ここで扱うのは、1台のデータベースサーバー(あるいは1つのクラスタ)の中で、論理的には1つの表を複数の物理単位へ分ける機能です。ノードをまたぐ分散とは別の話です。
1つの表を分割キーで小さな物理単位に切り分ける仕組みと呼び方の整理
パーティショニングでは、表の定義に分割キー(パーティションキー)を指定し、その値に応じて行がどの区画へ格納されるかを決める仕組みです。PostgreSQLの宣言的パーティショニングでは、親となるパーティション表と、実体を持つ子パーティションという構成を取ります。MySQLではPARTITION BY句を表定義に書き、内部で区画が分かれます。
呼び方は実装ごとに違い、MySQLのマニュアルでは「ユーザー定義パーティショニング」と表記されます。指しているものは同じで、SQL文の書き方が変わるだけです。アプリケーション側は分割前と同じSELECT文やINSERT文を投げられ、行き先の判定はデータベースが担います。
シャーディングやディスク領域の分割と混同しやすい三つの用語の線引き
「パーティション」という語は、少なくとも三つの文脈で使われます。一つ目がここで扱うデータベースの表分割、二つ目がディスク領域を区切るストレージの操作、三つ目がAmazon S3のプレフィックス設計などクラウドストレージのキー設計です。検索でたどり着いた記事が別の文脈だった、という取り違えが起きやすい語です。
実装判断で紛らわしいのは分散との違いです。表分割は1つのデータベース内で完結し、書き込み性能の上限は元のサーバーのままです。対して複数ノードへ行を配るのはシャーディングで、こちらはノード追加で書き込みを伸ばせる代わりに、JOINや一意性の担保がアプリケーション側の設計課題に変わります。同じ行の写しを複数ノードへ置くデータベースレプリケーションとも目的が違い、読み取り分散と冗長化はそちらの領分です。書き込みが詰まっているのに表分割へ手を出すと、狙った効果は出ません。
水平分割と垂直分割で変わる適用範囲と実装コストの違いの見極め方
行で切るのが水平分割、列で切るのが垂直分割です。データベースのパーティショニング機能が提供するのは水平分割で、垂直分割は表そのものを分けてJOINでつなぐ設計変更になります。
実装コストの差は大きく、水平分割はアプリケーションのSQLをほぼ変えずに導入できます。垂直分割はクエリの書き換えとトランザクション境界の再設計を伴うため、BLOBや長文カラムが読み取りを圧迫しているといった明確な理由がないと割に合いません。まず水平分割で足りるかを確かめ、1行が重すぎる場合に限って垂直分割を検討する。この順序を崩さないことです。
RANGE・LIST・HASHの三方式と分割キー選定で外さないための判断軸
分割方式の選択は、後から変えるコストが高い決定です。PostgreSQL公式ドキュメント(18系・2026年8月8日閲覧)は組み込みの形式としてレンジ・リスト・ハッシュの3種を挙げており、MySQL 8.4系も同様の分類を持ちます。
RANGE・LIST・HASHの三方式で変わる分割の粒度と向く用途の比較
三方式の性格は次のように整理できます。判断の起点は「その列で範囲検索をするか、値が固定的に列挙できるか」です。
| 方式 | 分け方 | 向く用途 | 注意点 |
|---|---|---|---|
| RANGE | 値の範囲で区切る | 期間で捨てる時系列データ | 上限側の受け皿が必要 |
| LIST | 値を列挙して割り当てる | 地域や区分など固定値 | 新しい値の追加漏れ |
| HASH | ハッシュ値の剰余で配る | 書き込みを均等に散らす | 範囲検索が全区画に及ぶ |
PostgreSQLのレンジ分割は上限が排他的な境界として扱われるため、月次で切るなら翌月1日を上限に置きます。ハッシュ分割は剰余(モジュラス)と余りの組み合わせで区画を定義する方式で、あとから区画数を変えると全行の再配置が発生します。
時系列データでRANGEが第一候補になる理由と境界値の決め方の実際
ログ、明細、計測値のように日付列を持つ表では、RANGEが第一候補になります。理由は検索と運用の両方に効くからです。直近1か月を見る画面は該当区画だけを読み、13か月より古いデータは区画ごと切り離して消せます。DELETE文で数千万行を消すときの長時間ロックも避けられます。
境界の粒度は、保存期間を区画数で割って決めます。3年保持なら月次で36区画、90日保持なら週次で13区画あたりが扱いやすい水準です。日次で3年分だと1,000区画を超え、計画時間とメタデータ管理の負担が増えます。
分割キーの候補を絞り込むカーディナリティと更新頻度から見た判断軸
分割キーに向く列の条件は3つあります。値の分布が偏っていないこと、更新されないこと、そして主要クエリの検索条件に必ず現れること。作成日時が定番なのは、この3つを同時に満たすからです。
ステータス列のように値が数個しかない列をHASHの分割キーに選ぶと、区画がほとんど分かれないまま管理コストだけが増える結果です。列の値の種類数がどれくらいあるかという観点は、インデックス設計と同じ判断軸で、カーディナリティの高低を先に確認しておくと候補を早く絞れます。分割キーの値が後から更新される設計は避けます。更新のたびに行が別区画へ移動し、削除と挿入に相当するコストがかかるためです。
サブパーティションと複合キーで膨らむ管理単位の数と見積もりの目安
RANGEで月次に分けたうえで、さらに各区画をHASHで4つに割る、といった二段構えがサブパーティショニングです。書き込みの集中を散らす効果はありますが、区画の総数は掛け算で増えます。
3年分の月次36区画にサブパーティション4つで144区画。数千を超える区画数は実行計画の作成時間とバックアップ対象の管理を圧迫するため、この程度までに収める前提で設計します。
パーティションプルーニングが効かない典型パターンと実行計画での確認手順
導入したのに速くならない、という相談のほとんどはここに原因があります。絞り込めているかどうかは、実行計画で確かめます。
WHERE句に分割キーが乗らないクエリで全パーティションを走査する構図
プルーニングは、WHERE句の条件から「この区画には該当行が無い」と証明できたときにだけ働く仕組みです。PostgreSQL公式ドキュメント(18系)は、この絞り込みを計画時と実行時の2段階で行うと説明しています。分割キーが条件に現れなければ、全区画を読む計画になります。
典型的な失敗は3つです。日付列で分割したのに、画面の検索条件が顧客IDだけになっている。分割キーに関数を適用した条件を書いている。ORでつないだ条件の片側に分割キーが無い。いずれも区画数が多いほど遅くなります。設計の初期に「主要な検索の10本すべてに分割キーが乗るか」を確認しておけば避けられる失敗です。
EXPLAINで実際に読まれたパーティション数と行数を確かめる手順
確認は実行計画で行います。PostgreSQLではEXPLAIN ANALYZEの出力に、計画時に除外された区画は現れません。実行時に除外された場合は「never executed」として区画が表示されます。MySQLではEXPLAINの出力にpartitions列があり、読み取り対象になった区画名が列挙されます。
見るべき数字は、対象区画の数と実際に読まれた行数の2つです。区画名が全件並んでいれば絞り込みは効いていません。クエリの実行の仕組みを押さえたうえで、分割前と分割後の同じSQLで実行計画を並べて比べると、効果の有無をその場で判断できます。確認は本番相当のデータ量で行ってください。数千行のテストデータでは差が出ません。
プリペアドステートメントで効く実行時プルーニングの条件と注意点
アプリケーションからはパラメータ化されたSQLを投げるのが普通で、計画を立てる時点では値が決まっていません。PostgreSQLはこの場合に実行時のプルーニングを行い、パラメータの値が定まってから不要な区画を読み飛ばします。
設定パラメータenable_partition_pruningが有効であることが前提です。同ドキュメントは既定値をonとしたうえで、これを無効にするとクエリが意図どおりに処理されないと明記しています。チューニング目的で設定を触った環境では、まずここが確認項目です。ORMが生成するSQLでも、分割キーがバインド変数として条件に含まれていれば絞り込みは働きます。
主キーと一意制約と外部キーに波及するパーティション化の制約の実像
分割方式より先に設計を止めるのが、制約まわりの条件です。既存表へ後から適用する場合、ここで断念する判断がしばしば発生します。
一意キーに分割キー列を含める必要があるMySQLとPostgreSQLの共通制約
MySQL 8.4のマニュアルは「分割表の分割式で使われるすべての列は、その表が持つすべての一意キーに含まれていなければならない」と定めています。PostgreSQL公式ドキュメント(18系)も、パーティション表に一意制約や主キーを作るには分割キー列をすべて含む必要があり、分割キーに式や関数呼び出しを含む場合は作成できないとしています。
実務への影響は具体的です。注文番号に一意制約があり、作成日時で分割したい表なら、主キーを(注文番号, 作成日時)の複合キーへ変える必要があります。外部システムが注文番号単体の一意性を前提にしている場合、アプリケーション側で重複を防ぐ責任が移ります。この一点だけで見送る判断になる案件は珍しくありません。
InnoDBの分割表で外部キーが使えないことによる設計への波及
MySQLではさらに厳しい条件があります。同マニュアルは、InnoDBの分割表は外部キーを持てず、外部キーで参照される側にもなれないと明記しています。参照する側・される側の両方向が対象です。
マスタ表と明細表が外部キーで結ばれた設計では、明細表を分割するために外部キー制約を落とすことになります。整合性の担保はアプリケーションの責務へ移り、テストの範囲も広がるでしょう。PostgreSQLはパーティション表を参照する外部キーを扱えます。データベース製品の違いがそのまま設計の自由度に出る領域なので、採用エンジンの前提を先に確認しておいてください。
パーティションごとに作られるインデックスと検索時の負担の増え方
PostgreSQLでパーティション表にインデックスを作ると、各区画に対応するインデックスが個別に作られます。全区画を横断する単一の索引は持ちません。分割キーが条件に無いクエリは、区画の数だけインデックスをたどることになります。
区画が12個なら12回、144個なら144回のインデックス探索が積み上がります。「細かく割るほど速くなる」という直感は成り立ちません。分割キーが乗らない検索が主要導線に残っているなら、その導線を先に設計し直すか、分割そのものを見送る判断になります。
パーティションの追加と切り離しを止めずに回すための運用設計の要件
分割は作った時点では完成しません。区画を足し続け、古い区画を落とし続ける仕組みまで含めて設計です。ここを詰めずに本番へ出すと、数か月後に障害として現れます。
古いデータの削除をDELETEから区画の切り離しへ置き換える効果
保存期間を過ぎたデータの削除は、分割の導入前後で作業が変わります。分割前は条件付きDELETEで数千万行を消し、トランザクションログの肥大と削除後の領域回収まで面倒を見ることになります。
分割後は、対象区画を切り離してから落とすだけで済みます。PostgreSQLならDETACH PARTITIONで親から外し、独立した表として保管するか削除。MySQLならDROP PARTITIONで区画ごと消します。行単位の削除処理が、メタデータ操作とファイル削除に置き換わる。この差が、月次バッチの実行時間を数時間から数分へ縮めます。
取得されるロックの粒度で変わる無停止での付け外しの可否と前提条件
無停止で運用できるかは、操作が取るロックの強さで決まります。PostgreSQL公式ドキュメント(18系)は、DETACH PARTITIONが親表に対してACCESS EXCLUSIVEロックを必要とする一方、CONCURRENTLY指定ではSHARE UPDATE EXCLUSIVEロックで済むと説明しています(ただし併用できない条件があります)。
区画の追加側も同様です。同ドキュメントは、ATTACH PARTITIONがパーティション表に対してSHARE UPDATE EXCLUSIVEロックしか必要とせず、CREATE TABLE … PARTITION OFが要求するACCESS EXCLUSIVEロックより弱いと述べています。空の表を先に作ってからATTACHする手順のほうが、稼働中の影響を抑えられるわけです。運用手順書にはどちらの構文を使うかまで書きます。
将来分の区画を自動で作る仕組みと生成が止まったときに起きる障害
RANGE分割で最も多い事故が、翌月分の区画の作り忘れです。行き先の区画が存在しないINSERTはエラーになり、書き込みが止まります。PostgreSQLにはDEFAULTパーティションがあり、どの区画にも当てはまらない行を受け止められますが、そこへ溜まった行は絞り込みの対象外になります。
対策は二段構えにします。将来分の区画を数か月先まで先行して作っておくこと。そのうえで、pg_partmanのような区画管理の拡張やジョブで自動生成し、生成の失敗を監視対象へ含めること。監視項目に「最も新しい区画の上限日付が現在日付から何日先か」を入れておくと、枯渇の何週間も前に気づけます。
パーティショニングを採用してよい規模と見送るべき場面の判断基準
ここまでの制約と運用要件を踏まえて、踏み切る線を明示します。ここは条件付きで言い切ります。
行数とデータ量と保存期間から見る導入に踏み切る目安の具体的な線引き
採用してよいのは、次の条件を同時に満たす場合です。単一表が1億行を超えるか、表とインデックスの合計サイズがサーバーの搭載メモリを上回っている。主要クエリの検索条件に日付など分割キーになる列が必ず含まれる。保存期間が定義されていて、期間を過ぎたデータを捨ててよい。
3つ目の条件が特に効きます。捨てるデータが無い表では区画運用のうまみが半減し、絞り込みの効果だけが残ります。データ量が増え続けるログ系・明細系で、直近しか参照されないもの。この形なら導入して間違いになりません。規模より先に「捨てられるか」を確認してください。
受託開発の現場でパーティション化を見送ると判断する典型的な条件
見送る条件も具体的に挙げます。まず、表の行数が数千万行以下の場合。インデックスの追加や不要インデックスの整理で足りることがほとんどで、区画運用の管理コストが上回ります。次に、分割キーを含まない一意制約が業務要件として動かせない場合。前述のとおり複合キー化が必須になり、外部連携の仕様変更まで波及します。
三つ目が、InnoDBで外部キーによる整合性担保を前提に組んである既存システムです。制約を落とす影響範囲がアプリケーション全体に及び、分割で得られる時間短縮に釣り合いません。四つ目が、検索導線が分割キー以外に散っている画面設計。ここは分割より先に、検索条件へ期間指定を必須化する設計変更のほうが効きます。迷ったら分割を見送り、保存期間の短縮とアーカイブ表への退避で済ませる。受託開発の現場では最も外れの少ない選択です。
分割を決める前に見直すインデックス設計と保存期間の点検の順序と体制
着手の順序を固定しておきます。第一に遅いクエリの実測と実行計画の確認、第二にインデックスの過不足の整理、第三に保存期間とアーカイブ方針の合意、第四にパーティショニングの検討。多くのケースは第二段階か第三段階で解決します。
第四段階まで来る規模のデータを扱うなら、区画設計とあわせて収集から保管、分析までの流れを一体で組み直すほうが手戻りは少なくなります。設計方針の整理や実装体制づくりを外部と組んで進めるなら、データ分析基盤構築・MLOps構築支援のように保持設計と運用まで含めて引き受ける支援の使い方が現実的です。分割の要否そのものを設計の初期段階で一緒に検証しておくと、後戻りのコストを抑えられます。
よくある質問
パーティショニングの導入検討でよく寄せられる質問を、実装判断の観点でまとめます。
パーティショニングを設定すれば検索は必ず速くなりますか?
速くなるとは限りません。効果が出るのは、WHERE句に分割キーが含まれて読む区画を絞り込めるクエリだけです。分割キーが条件に無いクエリは全区画を読み、インデックス探索も区画の数だけ発生するため、分割前より遅くなる場合があります。導入前に主要なクエリを洗い出し、分割キーが条件へ乗るかを実行計画で確認してください。PostgreSQLならEXPLAIN ANALYZEの出力に現れる区画、MySQLならEXPLAINのpartitions列を見ます。
何行くらいからパーティショニングを検討すべきですか?
目安は、単一表が1億行を超えるか、表とインデックスの合計サイズが搭載メモリを上回ったときです。数千万行の段階では、インデックスの見直しや不要な列の整理で改善するケースが大半で、区画運用の管理コストのほうが上回ります。行数より先に確認したいのは、保存期間が決まっていて古いデータを捨てられるかどうかでしょう。捨てる運用があるなら、規模が届いた時点で導入する価値があります。
既存の巨大な表に後からパーティショニングを適用できますか?
可能ですが、データの入れ替え作業が発生します。PostgreSQLの宣言的パーティショニングでは、既存の通常表をそのままパーティション表へ変換できません。パーティション表を新規に作って行を移し、切り替える手順を取ります。作業中の書き込みをどう扱うかは先に決めておいてください。あわせて、一意制約へ分割キー列を含める変更が要るかどうかを確認します。この制約変更が受け入れられないなら、適用そのものを見送る判断になります。
パーティションはいくつまで増やせますか?
MySQL 8.4のリファレンスマニュアルでは、NDB以外の表で作成できる区画の上限はサブパーティションを含めて8,192とされています。ただし上限まで作れることと運用に耐えることは別問題で、区画が数千を超えると実行計画の作成時間が延び、バックアップや監視の対象管理も煩雑になる傾向です。実務では数十から数百に収める設計を推奨します。
パーティション化した表でインデックスはどう作ればよいですか?
PostgreSQLではパーティション表に対してインデックスを作成すると、各区画に対応するインデックスが自動的に作られます。個別の区画にだけ索引を張る必要は通常ありません。設計上の注意は、区画を横断する単一の索引が存在しない点です。分割キーを含まない検索は区画の数だけ探索が積み上がるため、そうした検索が主要導線に残るなら区画数を抑えるか分割設計そのものを見直してください。MySQLでも索引は区画ごとに保持されます。
関連記事
- MySQLとは?特徴とバージョン選定・採用判断:分割機能の前提になるMySQLのバージョン差を整理しています
- PostgreSQLとMySQLの違いを徹底比較:制約の扱いが異なる2つのエンジンを比較しています
- データベースとは?種類・DBMSとRDB/NoSQLの選び方:分割を考える前提となる基礎を扱っています
- マテリアライズドビューとは?通常ビューとの違い:分割以外の高速化手段として比較できます
- スロークエリログとは|設定・見方と改善手順:分割の要否を実測から判断する手順を扱っています