シャーディング
データを複数のデータベースインスタンスに水平分割し、書き込みスループットとストレージ容量をスケールさせる手法
データベーススケーリング
シャーディングとは
シャーディング (Sharding) は、データを複数のデータベースインスタンス (シャード) に水平分割し、書き込みスループットとストレージ容量をスケールさせる手法である。1 台の DB では処理しきれないデータ量やトラフィックに対応する。
シャーディング前: 1 台の DB に全データ
シャーディング後:
シャード 0: userId 0〜999
シャード 1: userId 1000〜1999
シャード 2: userId 2000〜2999
シャーディング戦略
| 戦略 | 仕組み | メリット | デメリット |
|---|---|---|---|
| ハッシュ | キーのハッシュ値で分割 | データが均等に分散 | 範囲クエリが非効率 |
| レンジ | キーの範囲で分割 | 範囲クエリが効率的 | ホットスポットが発生しやすい |
| ジオベース | 地理的に分割 | レイテンシ最適化 | 地域間クエリが複雑 |
| ディレクトリ | ルックアップテーブルで分割先を決定 | 柔軟な分割 | ルックアップが単一障害点 |
DynamoDB の自動シャーディング
DynamoDB は内部的にシャーディングを自動で行う。パーティションキーのハッシュ値でデータを分散し、パーティション数はデータ量とスループットに応じて自動増加する。
// パーティションキーの設計が重要
// ❌ 悪い例: 日付をパーティションキーにすると、今日のパーティションに集中
{ PK: '2026-04-01', SK: 'order-123' }
// ✅ 良い例: userId をパーティションキーにすると、ユーザーごとに分散
{ PK: 'user-456', SK: 'order-123' }
RDS vs DynamoDB のシャーディング
| 観点 | RDS | DynamoDB |
|---|---|---|
| シャーディング | 手動 (アプリケーション側) | 自動 (パーティションキー) |
| リバランス | 手動 | 自動 |
| クロスシャードクエリ | 複雑 (全シャードに問い合わせ) | GSI で対応 |
| トランザクション | 分散トランザクション (2PC) が必要 | TransactWriteItems で 100 項目まで |
シャーディングの課題
クロスシャードクエリ
複数のシャードにまたがるクエリ (JOIN、集計) は、全シャードに問い合わせて結果をマージする必要がある。
「全ユーザーの注文合計」→ 全シャードに問い合わせ → 結果をマージ
「userId=123 の注文」→ シャード 0 だけに問い合わせ (効率的)
リシャーディング
データ量の増加に伴いシャード数を増やす場合、既存データの再配置が必要になる。コンシステントハッシュを使えば、再配置するデータ量を最小限に抑えられる。
トランザクション
複数シャードにまたがるトランザクションは、分散トランザクション (2PC) が必要になり、複雑さとレイテンシが増大する。
シャーディングを避ける方法
シャーディングは複雑さを大幅に増すため、他の手段で対応できないか先に検討する。
- リードレプリカ: 読み取り負荷の分散
- キャッシュ (ElastiCache): 頻繁に読まれるデータをキャッシュ
- インデックスの最適化: クエリパフォーマンスの改善
- DynamoDB: 自動パーティショニングでシャーディングが不要
DynamoDB を使えば、アプリケーション側でシャーディングを実装する必要がない。パーティションキーの設計だけに集中すればよい。
体系的に学ぶなら関連書籍を参照してほしい。