リレーションシップ
UI がユーザーを注文の隣に見せるから JOIN に手を伸ばすが、DynamoDB には
サーバー側の join 演算子がない。高くつく間違いは、各側を別々の GetItem で
取ること — 画面上の行ごとにスケールする N+1 読み取りだ。
DynamoDB のリレーションシップはキー設計に生きる。必要なグラフを 1 回の Query が
返すよう関連アイテムを同じアイテムコレクションに置くか、コレクションをまたいで
指す隣接行を維持する。多対多には明示的なブリッジパターンが要る。高いファンアウト
には複合ソートキーと、コレクションを境界内に保つための参照カウントが要ることがある。
読み終えたらできること
- 親のパーティションキーの下に子を同居させて一対多をモデル化できる。
- 各辺に完全なレコードを複製せず、隣接またはブリッジアイテムで多対多を実装できる。
- 複合ソートキーで広い階層を分割し、
begins_withクエリを精密に保てる。 - 「子が残っていない」に削除ルールが依存するとき、参照カウントをアトミックに維持できる。
読む順番
- 一対多 — 1 つのパーティションキーの 下の子。他のすべてのリレーションシップが拡張する基本パターン。
- 多対多 — どちらの側も他方を 一覧できるときのブリッジアイテムとデュアルライトパターン。
- 隣接リスト — アイテムと辺としての グラフ形データ。再帰 SQL なしの木の歩行。
- 複合ソートキー — ソートキーに階層を エンコードし、範囲クエリを選択的に保つ。
- 参照カウント — ファンアウトの一貫性が 必要なとき削除をゲートする条件付き更新。
PK = USER#88 のユーザープロフィールと SK = ORDER#2026-08-01#K4 の注文があれば、
1 回の Query でプロフィール画面を描ける。多対多のタググラフにはブリッジ行が
要る — そのステップを飛ばすと辺を探すために Scan することになる。
隣接リストは PARENT# / CHILD# ソートキー接頭辞で木と浅いグラフをモデル化し、
1 回の begins_with クエリが直接の子を返す。複合ソートキーは LOCATION#US#CA#SF
のようなパスをエンコードし、範囲クエリが部分木内に留まる。親アイテム上の参照
カウントが削除をゲートする。条件式の referenceCount = :zero は、まだプロダクトが
付いているカテゴリの削除を防ぐ。各パターンは書き込みの複雑さと読み取り効率を
交換する — 一覧の頻度とグラフを組み替える頻度のどちらに合うかを選ぶ。
DynoTable で手を動かす
DynoTable をダウンロードし、親/子キーのあるテーブルを開く。親
パーティションで Query を走らせ、グリッドがソート順でコレクション全体を
返すのを見る。複合キーのセルを右クリックして接頭辞でフィルターし、エンティティの
面が実際にどうまとまるかを見る。
それでもリレーショナルな見え方が欲しいときは、SQL Workbench
がすでに取得した行の上でクライアント側に JOIN を走らせる。その join は
DynamoDB が返したものに境界づけられる — サーバー側の join 演算子は追加しない。
キー設計の検証に使い、欠けたアクセスパターンを糊塗りするのに使わない。
アドホックな親/子レイアウトには、 シングルテーブル設計プランナー が 述べた読み取りから PK/SK 配置を提案する。