コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
シャーディング
シャーディング
このレッスンで分かること
- シャーディングが解決する「書き込みのスケール」問題
- シャードキーの選び方と典型的な失敗
- 分散環境での集計と JOIN の難しさ
シャーディング とは
水平分割でデータを分散し書き込みを拡張する手法。本レッスンでは、シャーディング の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
レプリケーションでは解けない問題
レプリケーションは読み取りはスケールしますが、書き込みは Primary 1 台に集中 したままです。書き込み秒間 10 万に達すれば、Primary が物理限界を迎えます。
これを解決するのが シャーディング (Sharding) です。データを複数のサーバに 水平分割 し、それぞれが Primary として書き込みを受け付けます。
各シャードは独立した DB で、自分の担当範囲のデータだけ持ちます。書き込みも読み取りもシャード単位で分散され、リニアにスケールします。
シャードキー
データをどのシャードに置くかを決めるカラムが シャードキー (Shard Key) です。実務では user_id が最も多く選ばれます。
分割方式
- レンジ分割 —
user_id 0-999 は Shard 1のように範囲で分ける - ハッシュ分割 —
hash(user_id) % 4でシャード番号を計算 - ディレクトリ分割 — 別途マッピングテーブルを持つ
| 方式 | 利点 | 欠点 |
|---|---|---|
| レンジ | 範囲スキャンが速い | 偏りが出やすい(新規ユーザーが Shard 4 に集中など) |
| ハッシュ | 均等分散 | 範囲スキャンが全シャード走査 |
| ディレクトリ | 柔軟、リバランス容易 | マッピング DB がボトルネック |
実務ではハッシュ分割が無難な選択肢で、TiDB や CockroachDB は内部でレンジ分割(自動リバランス付き)を採用しています。
シャードキー選びの難しさ
シャードキーは 後から変えられない ほぼ唯一の設計判断です。慎重に選ぶ必要があります。
良いシャードキーの条件は次の通りです。
- 値の カーディナリティが高い — 均等分散できる
- 値の 頻度分布が均一 — ホットスポットが出ない
- アクセスパターンの 大半に登場する — クロスシャードクエリが少ない
user_id は通常これらを満たしますが、country や region を選ぶと「日本ユーザーだけ激重」のような偏りが起きます。
クロスシャードクエリの罠
シャーディング後の最大の難所は 複数シャードにまたがるクエリ です。
SQL クエリ
-- 全ユーザーのうち今月登録した人数
SELECT COUNT(*) FROM users WHERE created_at > '2026-05-01';このクエリはシャードキーを使っていません。全シャードに同じクエリを投げ、結果を集約する必要があります。
- 集計関数 (
COUNT、SUM、MAX) — 各シャードで部分集計し、最後にアプリ側で合計 AVG—SUM / COUNTを別々に取り、後で計算ORDER BY ... LIMIT N— 各シャードから上位 N 件取り、合体してから再ソートJOIN— 結合キーがシャードキーでないと全シャードから持ってきて結合
これを Scatter-Gather と呼びます。並列にファンアウトしても応答時間は最も遅いシャードに律速され、シャードを増やすほど集約・調整のオーバーヘッドが増えるため、集計クエリの高速化にはつながりません。
シャードキーで絞れないクエリは「シャーディングの恩恵がない」。それを減らす設計が重要。
クロスシャードトランザクション
複数シャードにまたがる更新は 分散トランザクション が必要で、2 相コミット (2PC) などのプロトコルを使います。
- 性能が劇的に落ちる
- 一部シャードが落ちると全体が止まる
- デッドロックの検出が難しい
実務では「1 トランザクション = 1 シャード」になるよう設計するのが鉄則です。
リバランスの問題
シャード数を増やすときに、既存データを再分散させる必要があります。これが リバランス です。
ハッシュ分割で素朴に % 4 から % 5 に変えると、ほぼ全データが移動します。一貫性ハッシュ (Consistent Hashing) や 仮想シャード を使うと、移動量を全体の 1/シャード数 に抑えられます。
TiDB、CockroachDB、MongoDB Sharding などはリバランスを 自動 でやってくれます。手動シャーディングを実装するのはやめておきましょう。
いつシャーディングを導入するか
シャーディングは最後の手段です。次の順で検討します。
- クエリ最適化・インデックスチューニング
- 縦スケール(マシン強化)
- レプリケーションで読み取り分散
- 不要データのアーカイブ
- シャーディング
シャーディングを早すぎる段階で導入すると、開発生産性が激落ちする。1 台で耐える間は粘ろう。
アプリケーションシャーディング vs DB シャーディング
- アプリケーションシャーディング — アプリ側でシャード判別。MySQL や PostgreSQL を手動で分割
- DB ネイティブシャーディング — DB が透過的にシャードを管理。TiDB / Spanner / CockroachDB が代表
後者ならアプリは普通の SQL を書くだけで、DB が分散実行してくれます。これが次のレッスンで扱う NewSQL の世界です。
やってみよう
- 自分のプロジェクトの最大テーブルでシャードキー候補を 3 つ挙げ、それぞれの偏りリスクを評価する
hash(user_id) % 4で分散した場合、どのクエリが全シャードスキャンになるか書き出す- TiDB Cloud の無料プランで実際の分散環境を触ってみる
よくある質問
Q. このトピックは実務でどう役立ちますか?
A. DB のクエリ最適化、API 設計、データ構造の選択など、設計判断の根拠になります。表面的にライブラリを使うだけでなく「なぜそれが速いのか」を理解できると、性能問題を未然に防げます。コーディング面接でも頻出のテーマです。
Q. 計算量はどう求めれば良いですか?
A. ループのネストごとに掛け算する、再帰なら漸化式から解く、というのが基本です。Big-O 表記は定数倍と低次の項を無視するため、n の指数(n²、n log n など)に注目してください。最悪・平均・最良の 3 つを意識すると説得力が増します。
Q. 覚えるべき定番アルゴリズムは何ですか?
A. 二分探索、クイックソート/マージソート、BFS/DFS、ダイクストラ、DP の基本問題(フィボナッチ・ナップサック)が必修です。これらを「白紙から書ける」状態にすると、応用問題が一気に解けるようになります。
次のレッスン
次は CAP 定理 で、水平分割でデータを分散し書き込みを拡張する手法 を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- シャーディング の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. シャーディング とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン