TL

シャーディング方式:レンジ vs ハッシュ vs ディレクトリ

シャードキーの分け方を誤ると、再配置で停止したりホットスポットで分散が無に帰します。レンジ・ハッシュ・ディレクトリの再分散コストと範囲クエリ適性を対比し、選定の軸が分かります。

応用シャーディング分散システムパーティショニングスケーラビリティデータベース最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.レンジ分割は範囲クエリに強いがホットスポットを招きやすく、ハッシュ分割は均等だが範囲クエリが全シャードへ散る。ディレクトリ分割は対応表で柔軟だが表が単一障害点になる。
  • 2.再分散コストは方式で桁違い。レンジは分割/マージで局所的、ハッシュは固定スロット(仮想ノード)で局所化、素朴な mod N は全データ移動を招く。
  • 3.自動分割(split)は1パーティションがしきい値超で中央キーで二分し、自動マージ(merge)は隣接する小パーティションを統合する。境界はメタデータで管理する。

シャーディング方式を分ける3つの軸

シャーディングとは、1つの大きなデータ集合をシャードキーに基づいて複数のサーバー(シャード)へ水平分割することです。どのキーをどのシャードへ置くかを決める「割り当て関数」の選び方が、性能特性をほぼ決定づけます。実用上の選択肢は大きく3系統に分かれます。

  • レンジ分割(range): シャードキーの値域を連続した区間に切り、[a, b) のような帯ごとにシャードへ割り当てる。
  • ハッシュ分割(hash): キーをハッシュ関数に通し、その出力でシャードを決める。連続したキーが意図的に散らばる。
  • ディレクトリ分割(directory / lookup): キーとシャードの対応を明示的なルックアップ表で持ち、表を引いて宛先を決める。

この3つを評価する軸は主に (1) 再分散コスト、(2) ホットスポット耐性、(3) 範囲クエリ適性 の3つです。順に原理を見ていきます。

レンジ分割:境界で切る

レンジ分割は、シャードキーの値域を順序付きの区間に切ります。たとえばタイムスタンプを 2026-012026-02… の月ごとに、あるいはユーザー ID を 1–9999991000000–1999999… の帯に割り当てます。各シャードは境界キー(split key)の組で表現され、メタデータとして「どの区間がどのシャードか」を保持します。

宛先の決定は、キーが属する区間を二分探索で引くだけで O(log P)(P はパーティション数)で済みます。

境界テーブル(ソート済み)
  (-∞, 1000000)        -> shard A
  [1000000, 2000000)   -> shard B
  [2000000, 3000000)   -> shard C
  [3000000, +∞)        -> shard D

key=1500000 -> 二分探索で [1000000,2000000) -> shard B

最大の利点は範囲クエリの局所性です。WHERE id BETWEEN 1200000 AND 1300000 のような問い合わせは単一シャード(または隣接する少数のシャード)で完結し、連続スキャンが効きます。時系列データの「直近1週間」取得などはレンジ分割の独擅場です。

レンジ分割はホットスポットの温床

レンジ分割の弱点は負荷の偏りです。単調増加するキー(連番 ID・タイムスタンプ)をそのまま境界に使うと、新規書き込みが常に最後のシャードへ集中します。これを末尾ホットスポット(append hotspot)と呼びます。読み取りでも、人気の区間に偏ればその担当シャードだけが過負荷になります。回避策はキーの先頭にハッシュやランダムなプレフィックスを付ける(ソルティング)、複合キーで分散軸を足す、などですが、いずれも範囲クエリ適性とのトレードオフになります。

ハッシュ分割:散らして均す

ハッシュ分割は、キーを h = hash(key) に通し、その値でシャードを決めます。良いハッシュ関数は出力を一様分布させるため、連続したキーが別々のシャードへ散り、負荷とデータ量が均等になりやすいのが本質的な強みです。末尾ホットスポットは構造的に起きません。

問題は再分散コストで、ここで素朴な実装と洗練された実装が分かれます。最も単純な shard = hash(key) % N(mod N 方式)は、シャード数 N が変わった瞬間に剰余の周期が変わり、ほとんどのキーが別シャードへ移動します。10台を11台にしただけで9割近いキーが再配置対象になる計算で、運用中のシステムでは破綻します。

実務ではこれを避けるため、固定スロットを挟みます。物理シャード数とは独立に、ハッシュ空間をあらかじめ多数のスロット(仮想ノード/トークン)に分け、スロットを物理シャードへ割り当てる二段構えにするのです。

key -> hash -> slot(固定多数、例 4096個)-> シャード(可変少数)

slot = hash(key) % 4096          # スロット数は不変
shard = slot_to_shard[slot]      # 割り当て表だけを書き換える

シャードを増減するときはスロットの割り当てだけを付け替えます。動くのは移譲したスロットぶんのデータだけで、移動量は全体の約 1/N に抑えられます。これがコンシステントハッシュ法の発想で、Cassandra や DynamoDB 系の分散ストアが採用する標準解です。

ハッシュ分割は範囲クエリを全シャードへ散らす

ハッシュ分割の代償は範囲クエリの壊滅的な非効率です。連続したキーは一様に散らばっているため、BETWEEN のような区間取得は全シャードへ問い合わせて結果をマージするしかありません(scatter-gather)。レイテンシは最も遅いシャードに引きずられ、台数が増えるほどテール遅延が悪化します。範囲スキャンが主用途ならハッシュ分割は不向きで、レンジ分割を選ぶべきです。

ディレクトリ分割:対応表で明示する

ディレクトリ分割は、割り当てを関数で計算する代わりに、キー(またはキー群)→ シャードの対応を独立したルックアップサービスに持たせます。書き込み・読み取りの前にまず表を引き、宛先シャードを得てから本体へアクセスします。

最大の利点は柔軟性です。任意のキーを任意のシャードへ置けるため、ホットなテナントだけを専用シャードへ隔離する、容量の空いたシャードへ個別に寄せる、といった運用が表の更新だけで可能です。再分散も「表のエントリを書き換えて該当データを移す」だけで、関数の制約に縛られません。

ルックアップ表(テナント単位の例)
  tenant=ACME    -> shard C (大口・専用)
  tenant=foo     -> shard A
  tenant=bar     -> shard A
  tenant=baz     -> shard B  (旧 A から個別移動)

参照のたびに表を引いてから本体へ

代償は間接層のコストです。表は全アクセスの経路上にあるため、可用性とレイテンシのボトルネックになりえます。表を持つサービスが落ちれば全体が止まる単一障害点になりかねず、実際には表自体をレプリケーション・キャッシュして守る必要があります。表が巨大になりすぎないよう、行単位ではなくテナントや範囲のまとまり単位で対応を持つのが定石です。

3方式の対比

観点レンジハッシュディレクトリ
割り当ての決め方境界キーの区間ハッシュ値→スロット明示的な対応表
範囲クエリ適性高い(単一/少数シャード)低い(全シャードへ散る)表の設計次第・原則低い
ホットスポット耐性低い(末尾・人気区間に集中)高い(一様分散)中(偏れば個別に隔離可)
再分散コスト局所的(split/merge)スロット方式なら約 1/N、mod N は全移動局所的(表更新+当該データ移動)
メタデータ/障害点境界表(小)スロット割り当て表表が単一障害点になりやすい
代表例HBase, 時系列DBCassandra, DynamoDB大規模マルチテナント基盤

実システムは純粋な1方式とは限りません。たとえば「テナントはディレクトリで振り分け、テナント内はレンジ」のような複合方式が一般的です。

自動分割(split)と自動マージ(merge)の原理

レンジ分割系のストアは、データの増減に応じてパーティションを動的に分割・統合します。これが自動シャーディングの中核です。

自動分割(split) は、あるパーティションのサイズや負荷がしきい値を超えたとき、その区間を二分する処理です。境界をどこに置くかが肝で、キーが偏在していると単純な中点では均等になりません。実装は**中央値に近いキー(median key)**を選んで分割点とします。

split の擬似コード

if partition.size > SPLIT_THRESHOLD:
    mid = approximate_median_key(partition)   # サンプリングで近似
    left  = partition.range_below(mid)        # [start, mid)
    right = partition.range_from(mid)         # [mid, end)
    metadata.replace(partition, [left, right])
    schedule_move(right, pick_target_shard()) # 片方を別シャードへ移す

ポイントは、分割が境界メタデータの更新であり、データ本体を物理的に並べ替える必要が原則ない点です。区間が二つに割れ、片方の担当が新しいシャードへ移譲されるだけなので、影響は局所に閉じます。中央値はストレージの統計(ヒストグラムやサンプリング)から近似します。

自動マージ(merge) はその逆で、隣接する小さなパーティションを統合します。古いデータの削除や TTL でスカスカになった区間を放置するとパーティション数だけが膨れ、メタデータと管理コストが無駄に増えるためです。マージはキー順で隣接するパーティション同士でしか行えません(区間の連続性を保つ必要があるため)。ハッシュ分割では隣接概念が値域上にないので、マージは主にレンジ系の操作です。

境界はデータと分離して管理する

split/merge が安価に成り立つのは、どの区間がどのシャードかという境界情報を、データ本体とは別のメタデータ層(ルーティングテーブル)で管理しているからです。クライアントはこの表をキャッシュして直接シャードへ届け、表が古ければリダイレクトで学習し直します。HBase のリージョン、TiDB の Region、CockroachDB の Range はいずれもこの「自動 split/merge されるレンジ単位+ルーティングメタデータ」というモデルを採っています。

試験・面接での頻出ポイント

頻出は「範囲クエリに強いのはどの方式か」(レンジ)、「末尾ホットスポットが起きるのは」(単調増加キーのレンジ分割)、「mod N の再分散コストは」(ほぼ全データ移動、ゆえにスロット/コンシステントハッシュで回避)、「ディレクトリ分割の弱点は」(対応表が単一障害点)です。自動分割の境界選定で中央値を使う理由(偏りを均すため)も問われます。

まとめ

まとめ

シャーディング方式は 割り当て関数の選び方 で決まります。レンジは範囲クエリに強い一方で末尾・人気区間のホットスポットを招き、ハッシュは一様分散で均等だが範囲クエリが全シャードへ散ります(mod N は全移動を招くためスロット方式で局所化)。ディレクトリは対応表で柔軟に再配置・隔離できる代わりに表が単一障害点になりがちです。自動 split は中央値で区間を二分し、自動 merge は隣接する小区間を統合します。いずれも境界をデータと分離したメタデータ層で管理することで局所的に成立します。基礎はパーティショニングレプリケーションとシャーディング、データモデル選定はRDBとNoSQLも合わせてどうぞ。

データベース Article

シャーディング方式:レンジ vs ハッシュ vs ディレクトリを実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

シャーディング

比較で見る軸

難易度: advanced / カテゴリ: データベース / タグ数: 5

導入後に効く点

再分散コストは方式で桁違い。レンジは分割/マージで局所的、ハッシュは固定スロット(仮想ノード)で局所化、素朴な mod N は全データ移動を招く。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
データベース
タグ数
5

判断チェックリスト

  • 自社の用途が「シャーディング / 分散システム」に近いか確認する。
  • 強みである「レンジ分割は範囲クエリに強いがホットスポットを招きやすく、ハッシュ分割は均等だが範囲クエリが全シャードへ散る。ディレクトリ分割は対応表で柔軟だが表が単一障害点になる。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

シャーディング分散システムパーティショニングスケーラビリティデータベースシャーディング分散システムパーティショニング