DDIA 第6章:パーティショニング
Tony Duong
3月 18, 2026 · 1 分
#ddia#databases#partitioning#sharding#distributed-systems
概要
Designing Data-Intensive Applications の第6章は パーティショニング(シャーディング)を扱う:大きなデータセットを小さな断片に分割し、複数ノードに分散する。パーティショニングはレプリケーションと組み合わせて使う — 各パーティションは障害耐性のためレプリケートできる。目的は書き込みスループットとストレージを単一マシンを超えてスケールさせること。
キーバリューデータのパーティショニング
- キー範囲によるパーティショニング: 連続したキー範囲(例:A–M、N–Z)をノードに割り当てる。シンプルで範囲スキャンに有利。リスク:アクセスが偏ると ホットスポット(例:「A」で始まるキーにトラフィック集中)。
- キーのハッシュによるパーティショニング: キーをハッシュし、ハッシュ範囲で割り当てる。データが均等に分散し、辞書順によるホットスポットを避けられる。欠点:範囲クエリ が非効率 — 全パーティションに問い合わせる必要がある。
- ハイブリッド: 複合キー(例:hash(user_id) + timestamp)でハッシュでパーティションしつつ、第二要素でパーティション内の範囲スキャンが可能になる。
パーティショニングとセカンダリインデックス
セカンダリインデックス(例:「ユーザー X の全投稿を検索」)はパーティションにきれいにマップしない。主に二つのアプローチ:
- ローカル(ドキュメント)インデックス: 各パーティションが自パーティションのデータだけに対するセカンダリインデックスを保持。セカンダリキーでのクエリは scatter-gather になる:全パーティションに送り結果をマージ。シンプルだが読み取りコストが高い。
- グローバルインデックス: 一つのセカンダリインデックス自体がパーティションされる(例:インデックスキーで)。読み取りはインデックスの一パーティションへ;書き込みはドキュメントが一パーティションにありインデックスエントリが別にあると複数パーティションの更新が必要。書き込みは複雑、読み取りは的を絞れる。
リバランス
ノードの追加・削除時に、パーティションを公平に配分するためデータを移動する。
- 難しい理由: データ移動はコストがかかる;移動量を抑え、ノードの過負荷やダウンタイムを避けたい。
- 戦略: (1) 固定数のパーティション — ノード数より多いパーティション;ノード追加時に既存パーティションの一部を割り当て。シンプルだがパーティション数は作成時に固定。(2) 動的パーティショニング — パーティションが大きくなりすぎたら分割(LSM/SSTables のように)。(3) ノード数に比例したパーティション — パーティション数=ノード数;クラスタサイズ変更時に分割/マージ。Cassandra などで使用。
- 運用: 自動または手動リバランス;一ノードに決定を任せない(SPOF 回避)。Raft などのコンセンサスでパーティション割り当てが可能。
リクエストルーティング
クライアントがキーを読み書きするとき、どのノードに聞けばよいか?
- 任意のノードがルーティング: 接触したノードが正しいパーティションへ転送。クライアントは任意のノードに話せる。ノードはパーティション割り当て(例:ZooKeeper などのコーディネータから)を知る。
- ルーティング層: ロードバランサー、プロキシ、クラスタ対応クライアントなどが割り当てを知り、リクエストをルーティング。
- クライアントが割り当てを知る: クライアントがパーティションマップ(例:コーディネータから)を取得し、正しいノードに直接話す。ホップは減るがクライアントは最新を保つ必要がある。
多くのシステムでは ディレクトリサービス(etcd、ZooKeeper など)がパーティション→ノードのマッピングを保持し、ノードやクライアントが変更を購読する。
ポイント
- パーティショニング によりストレージと書き込みスループットをノード間分散でスケールできる;レプリケーションと組み合わせることが多い。
- キー範囲 パーティショニングは範囲クエリを支えるがホットスポットを生みうる;ハッシュ パーティショニングは負荷を分散するが効率的な範囲スキャンを失う。
- セカンダリインデックス は選択を迫る:ローカルインデックス(scatter-gather 読み)かグローバルインデックス(的を絞った読み、より複雑な書き込み)。
- リバランス は慎重に(固定・動的・比例);データ移動を最小化し単一障害点を避ける。
- リクエストルーティング にはどのパーティションがどのノードにあるかの一貫した見えが必要 — ディレクトリサービス、ルーティング層、クライアント側割り当てで実現。
Claudeによる翻訳