DynamoDBはRDBの延長で設計すると必ず詰まります。アクセスパターンを先に固め、PK/SK・GSIで表現し、ホットパーティションを避ける。その設計順序と、シングルテーブル設計を採るべきかの判断軸を整理します。
01まず「アクセスパターンを先に決める」を体に叩き込む
DynamoDBでもっとも重要な原則は、スキーマより先にアクセスパターンを決めることです。AWSの公式ドキュメントは「DynamoDBのスキーマ設計は、それが答えるべき問い(クエリ)が分かるまで始めるべきではない」と明言しています。RDBのように正規化してから後付けでクエリを最適化する、という順番は通用しません。
RDBMSは「柔軟にクエリできるが、複雑なクエリは高コストでスケールしにくい」、DynamoDBは「限られた方法なら極めて効率よくクエリできるが、それ以外は高コストで遅い」——この非対称性が設計思想の違いの根っこです。DynamoDBでは最頻・最重要のクエリを最速・最安にするようにデータ構造を作り込みます。
実務では、テーブルを引く前に次の3点を洗い出します。AWSが挙げる「データサイズ・データ形状・データ速度(velocity)」の三属性です。
- データサイズ:一度にどれだけ保存・取得するか。パーティション分割の粒度を決める。
- データ形状:クエリ時にデータを整形するのではなく、クエリ結果の形のまま格納する。
- データ速度:ピーク時のクエリ負荷。I/Oを分散させるキー設計の前提になる。
誰が/何をキーに/どの順で/どれくらいの頻度でを全部書き出す。ここが埋まっていないうちにテーブル定義を書き始めるプロジェクトは、ほぼ確実に作り直します。02PK/SKの基本 — 単純キーと複合キー
DynamoDBのプライマリキーは2種類あります。単純キー(パーティションキーのみ)と複合キー(パーティションキー+ソートキー)です。パーティションキー(PK)はアイテムをどの物理パーティションに置くかを決め、ソートキー(SK)は同一PK内での並び順を決めます。
同じPKを持つアイテム群は「アイテムコレクション」として同じパーティション上にまとまって置かれます。ここが設計のツボで、PKで絞り込み、SKの範囲(begins_with、between等)で効率よく取り出すのがQueryの基本形です。Scanは全件走査なので、本番の主要導線では原則使いません。
RDBから来た人がやりがちなのは、Queryで「PKを指定せず条件だけで検索」しようとすることです。DynamoDBのQueryはPKの完全一致が必須で、SKでしか範囲・部分一致は使えません。PKをまたいだ検索が必要なら、それは別のアクセスパターンであり、後述のGSIで表現します。
ORDER#2026-07-08#1234 のように「エンティティ種別+ソートしたい値」を連結した文字列を入れる設計が定番です。文字列の辞書順ソートを利用して、begins_with(SK, "ORDER#") で特定種別だけを、日付プレフィックスで時系列順に、といった取り出しが1回のQueryで済みます。03ホットパーティション — 一番刺さる落とし穴
DynamoDBの各パーティションは最大 3,000 read units/秒・1,000 write units/秒を上限に設計されています(公式値、最新は公式で確認)。1 read unitは4KBまでのアイテムに対する強整合読み取り1回(結果整合なら2回)、1 write unitは1KBまでの書き込み1回に相当します。単一のPK値へのアクセスがこの閾値を超えると、テーブル全体に余裕があっても ProvisionedThroughputExceededException でスロットリングされます。これがホットパーティションです。
アイテムサイズの換算も忘れがちです。公式の例では、20KBのアイテムに対する強整合読み取り1回は5 read unitsを消費するため、単一アイテムには秒間600回までしか読めません。大きいアイテムほど、同じPKで捌ける件数は減ります。
設計上の原則は「アイテム数に対してできるだけ多くの異なる値を取るPKを選ぶ」こと。ステータスや国コードのように値の種類が少ないカラムをPKにすると、特定値にアクセスが集中してホット化します。書き込みが特定PKに集中する(目安として1,000 writes/秒超)ケースでは、ライトシャーディング——PK末尾に#0〜#Nの乱数サフィックスを付けて分散させ、読み取り時はN個を並列Queryする——を検討します。
なおDynamoDBにはアダプティブキャパシティがあり、これはオンデマンド・プロビジョンド両モードで働きます。偏った負荷をある程度は自動で吸収してくれますが、単一PK値の 3,000/1,000 という物理上限そのものは超えられません。アダプティブ任せの設計にせず、キー設計で分散させるのが本筋です。
04GSIとLSI — 別の切り口でクエリする
「PKをまたいで検索したい」「別の属性でソートしたい」という要件は、セカンダリインデックスで表現します。DynamoDBには2種類あります。
- GSI(グローバルセカンダリインデックス):ベーステーブルと異なるPK/SKを持てる。全パーティションを横断するクエリが可能。テーブル作成後にも追加・削除できる。独自のキャパシティを持ち、非同期でレプリケートされるため結果整合のみ。
- LSI(ローカルセカンダリインデックス):ベーステーブルと同じPKで、SKだけ別にできる。強整合読み取りが可能だが、テーブル作成時にしか定義できず、同一PK内のアイテムコレクションに10GBの上限がかかる。
実務ではほとんどの新規要件をGSIで表現します。後付けできる柔軟性と、強整合が要らない多くのユースケースにフィットするからです。LSIは「同一PK内で強整合の別ソートが絶対に必要」という限定的な場面に限られます。
KEYS_ONLYやINCLUDEで本当に必要な属性だけを射影するのが鉄則です。05シングルテーブル設計 — 考え方と是非
DynamoDBの上級パターンがシングルテーブル設計です。ユーザー・注文・明細といった複数エンティティを、1つのテーブルにPK/SKを汎用的に使い分けて同居させます。AWSも「DynamoDBアプリケーションではテーブル数はできるだけ少なく保つべき」とし、locality of reference(関連データを一箇所に置く)を性能原則として挙げています。
狙いは、1回のQueryで関連する複数エンティティをまとめて取得することです。例えば「ユーザーとその注文一覧を1リクエストで」を、同一PK(USER#123)配下にユーザー本体アイテムと注文アイテムを並べることで実現します。RDBのJOINをキー設計で事前に「焼き込む」イメージです。
ただし、シングルテーブル設計は万能ではありません。AWS自身、時系列データや「アクセスパターンが大きく異なるデータセット」は例外だと述べています。是非は次の判断軸で決めます。
- 採用が効くケース:エンティティ間のリレーションが密で、「関連データを1回で取る」導線が多い。マイクロサービスのバックエンドで低レイテンシが至上命題。
- 分けた方がよいケース:エンティティごとにアクセス頻度・ライフサイクルが大きく違う。時系列データでテーブルのローテーション(TTLや期間別テーブル)を使いたい。チームの習熟度が低く、汎用キーの運用が破綻しそう。
PK/SK/GSI1PKだらけになったテーブルを、半年後に引き継ぐチームが読めるかも設計判断の一部です。06オンデマンド vs プロビジョンド — キャパシティモードの選定
DynamoDBのスループットモードは2つ。課金体系がまったく違うので、ここは明確な判断軸で決めます。
- オンデマンド:リクエスト単位の従量課金。キャパシティ計画・監視・スケーリング設定が不要。AWSは「ほとんどのワークロードでデフォルトかつ推奨」と位置づけています。トラフィックが読めない・スパイクする・新規サービスに向く。
- プロビジョンド:秒間の読み書き容量を事前指定し、消費量ではなく確保した容量に対して時間課金。安定・予測可能な負荷で、容量を確実に見積もれるなら単価が有利。Auto Scalingや予約キャパシティと組み合わせてコスト最適化する。
| 判断軸 | オンデマンド | プロビジョンド |
|---|---|---|
| トラフィックの予測可能性 | 読めない/スパイクする | 安定・予測可能 |
| 運用の手間 | 最小(計画不要) | 見積り・Auto Scaling設定が必要 |
| コスト特性 | 使った分だけ、ピーク前提不要 | 高稼働率なら単価有利 |
| 向くフェーズ | 新規/検証/変動大 | 定常運用/大規模安定負荷 |
迷ったらまずオンデマンドで始め、負荷が定常化してデータが揃ってからプロビジョンドへ切り替えるのが定石です。モード切替は可能ですが頻度に制約があるため、公式のガイドで最新の制約を確認してください。料金・上限値はバージョン依存なので必ず公式で最新を確認します。
07コスト設計で見落とされる点
DynamoDBの請求は「テーブルのRCU/WCU」だけではありません。実務で効いてくるのは次の要素です。
- GSIの書き込み増幅:GSIを1本足すと、その対象属性を更新するたびにベース+GSI分の書き込みが発生。GSIを3本持てば単純計算で書き込みコストは膨らみます。射影属性を絞るのが最大の効き所。
- アイテムサイズ:WCUは1KB単位、RCUは4KB単位。1アイテムが肥大すると1回の操作で複数ユニットを消費。大きなBLOBはS3に置いてキーだけDynamoDBに、が定石です。
- ストレージ:ベーステーブルに加え、GSIの射影分もストレージ課金の対象。
- 結果整合を活かす:強整合読み取りは結果整合の2倍のRCUを消費。強整合が要らない導線は明示的に結果整合にする。
関連するデータストア選定として、リレーショナルが本命ならAurora と RDS の選定、キャッシュ層はElastiCache(Redis)の実務も併せて検討してください。全体のアカウント統制はマルチアカウント統制の枠組みで揃えます。
08RDBから来た人がハマる所(チェックリスト)
最後に、RDB経験者がDynamoDBで踏みやすい地雷を並べます。設計レビューのチェックリストとして使ってください。
- 正規化しすぎる:DynamoDBは意図的な非正規化・データ重複が正解の場面が多い。JOINが無い前提で、読みたい形のまま持つ。
- Scanに頼る:
Scanは全件走査。主要導線は必ずQuery(PK一致)かGetItemで設計する。 - アクセスパターンを後回しにする:テーブル定義から書き始めない。パターン一覧が先。
- 値の種類が少ないカラムをPKにする:ステータスやフラグをPKにするとホット化する。
- GSIをALL射影で乱造する:コストとストレージが跳ねる。必要属性だけ射影。
- 強整合をデフォルトにする:多くの導線は結果整合で十分。RCUが2倍違う。
- LSIを後から足そうとする:LSIはテーブル作成時のみ。後付けはGSIで。
- 1アイテムに巨大データを詰める:大きなペイロードはS3へ。DynamoDBには参照キーだけ。
DynamoDBが絡む設計を、周辺のデータレイクや監視まで含めて俯瞰したい場合はS3データレイク設計や監視・アラート設計も参考になります。
—まとめ
DynamoDB設計は「アクセスパターンを先に決め、PK/SKとGSIでそれを表現し、キー設計でホットパーティションを避ける」に尽きます。シングルテーブル設計は密結合エンティティの低レイテンシ取得に強力ですが、時系列や毛色の違うデータは分けるのが現実解です。キャパシティモードはまずオンデマンド、定常化してからプロビジョンドを検討。そしてGSIの射影・アイテムサイズ・強整合の使いどころがコストを左右します。数値・料金・上限はバージョン依存のため、必ず公式ドキュメントで最新を確認してください。設計の入口であるアクセスパターンの棚卸しから支援が必要でしたら、お問い合わせください。実際の導入事例もあわせてご覧いただけます。