コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB

シャーディング

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

シャーディング

このレッスンで分かること

  • シャーディングが解決する「書き込みのスケール」問題
  • シャードキーの選び方と典型的な失敗
  • 分散環境での集計と JOIN の難しさ

シャーディング とは

水平分割でデータを分散し書き込みを拡張する手法。本レッスンでは、シャーディング の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

レプリケーションでは解けない問題

レプリケーションは読み取りはスケールしますが、書き込みは Primary 1 台に集中 したままです。書き込み秒間 10 万に達すれば、Primary が物理限界を迎えます。

これを解決するのが シャーディング (Sharding) です。データを複数のサーバに 水平分割 し、それぞれが Primary として書き込みを受け付けます。

diagram (will load when visible)

各シャードは独立した DB で、自分の担当範囲のデータだけ持ちます。書き込みも読み取りもシャード単位で分散され、リニアにスケールします。

シャードキー

データをどのシャードに置くかを決めるカラムが シャードキー (Shard Key) です。実務では user_id が最も多く選ばれます。

分割方式

  • レンジ分割user_id 0-999 は Shard 1 のように範囲で分ける
  • ハッシュ分割hash(user_id) % 4 でシャード番号を計算
  • ディレクトリ分割 — 別途マッピングテーブルを持つ
方式利点欠点
レンジ範囲スキャンが速い偏りが出やすい(新規ユーザーが Shard 4 に集中など)
ハッシュ均等分散範囲スキャンが全シャード走査
ディレクトリ柔軟、リバランス容易マッピング DB がボトルネック

実務ではハッシュ分割が無難な選択肢で、TiDB や CockroachDB は内部でレンジ分割(自動リバランス付き)を採用しています。

シャードキー選びの難しさ

シャードキーは 後から変えられない ほぼ唯一の設計判断です。慎重に選ぶ必要があります。

良いシャードキーの条件は次の通りです。

  • 値の カーディナリティが高い — 均等分散できる
  • 値の 頻度分布が均一 — ホットスポットが出ない
  • アクセスパターンの 大半に登場する — クロスシャードクエリが少ない

user_id は通常これらを満たしますが、countryregion を選ぶと「日本ユーザーだけ激重」のような偏りが起きます。

クロスシャードクエリの罠

シャーディング後の最大の難所は 複数シャードにまたがるクエリ です。

SQL クエリ

-- 全ユーザーのうち今月登録した人数 SELECT COUNT(*) FROM users WHERE created_at > '2026-05-01';

このクエリはシャードキーを使っていません。全シャードに同じクエリを投げ、結果を集約する必要があります。

  • 集計関数 (COUNTSUMMAX) — 各シャードで部分集計し、最後にアプリ側で合計
  • AVGSUM / COUNT を別々に取り、後で計算
  • ORDER BY ... LIMIT N — 各シャードから上位 N 件取り、合体してから再ソート
  • JOIN — 結合キーがシャードキーでないと全シャードから持ってきて結合

これを Scatter-Gather と呼びます。並列にファンアウトしても応答時間は最も遅いシャードに律速され、シャードを増やすほど集約・調整のオーバーヘッドが増えるため、集計クエリの高速化にはつながりません。

シャードキーで絞れないクエリは「シャーディングの恩恵がない」。それを減らす設計が重要。

クロスシャードトランザクション

複数シャードにまたがる更新は 分散トランザクション が必要で、2 相コミット (2PC) などのプロトコルを使います。

  • 性能が劇的に落ちる
  • 一部シャードが落ちると全体が止まる
  • デッドロックの検出が難しい

実務では「1 トランザクション = 1 シャード」になるよう設計するのが鉄則です。

リバランスの問題

シャード数を増やすときに、既存データを再分散させる必要があります。これが リバランス です。

ハッシュ分割で素朴に % 4 から % 5 に変えると、ほぼ全データが移動します。一貫性ハッシュ (Consistent Hashing)仮想シャード を使うと、移動量を全体の 1/シャード数 に抑えられます。

TiDB、CockroachDB、MongoDB Sharding などはリバランスを 自動 でやってくれます。手動シャーディングを実装するのはやめておきましょう。

いつシャーディングを導入するか

シャーディングは最後の手段です。次の順で検討します。

  1. クエリ最適化・インデックスチューニング
  2. 縦スケール(マシン強化)
  3. レプリケーションで読み取り分散
  4. 不要データのアーカイブ
  5. シャーディング

シャーディングを早すぎる段階で導入すると、開発生産性が激落ちする。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 つができることを確認しましょう。

  1. シャーディング の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. シャーディング とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン