Dev Study
AWSサービスの内部原理 コース

7. ソートキーは物理配置を決める — 複合主キーとアイテムコレクション

ソートキーがデータの物理的な並びと検索の速さをどう決めるのか、図で追っていきましょう。

①1つの複合主キー、2つの役割

複合主キーの役割分担
複合主キー例: Artist + SongTitle
2つの属性に分解
パーティションキーハッシュ関数に通す
格納先を決める
ソートキー値の昇順に整列
並び順を決める
どのパーティションか
パーティション内の物理配置
  • ・公式: 同じパーティションキー値の全項目は、ソートキー値の昇順に並べてまとめて格納される
  • ・ソートキーは単なる識別子の一部ではなく、物理的な並びを指定する属性

パーティションキーは「どこに置くか」、ソートキーは「その中でどう並べるか」を決める。役割はまったく別。

②アイテムコレクションとLSIの分かれ道

コレクションはどこに収まる?
item collection同じPK値を持つ項目群
テーブルにLSIは?
LSIなし必要なだけ複数パーティションに自動分割
サイズ上限なし
LSIあり各コレクションは1パーティションに固定
10GBの壁
  • ・公式の言い回しは「近くにまとめソート順に保つ傾向がある」— あくまで傾向
  • ・10GB上限はLSIなしのテーブルには適用されない
  • ・この条件は後のLSIレッスンの容量設計の土台になる

同じパーティションキー値の項目群= item collection。LSIの有無で「どこに収まるか」が変わる。

③ソート済みだから範囲検索が速い

Queryが範囲を読む流れ
Querybegins_with / between をソートキーに指定
PKでコレクション先頭へ一発到達
ソート済みコレクション隣接して格納された項目
開始位置から隣を順にたどる
条件に合う範囲だけ読む
O(log n + k)
未整列なら…全件を舐めるしかない
  • ・開始位置は対数時間で発見(各レプリカがB木を持つ — DynamoDB論文)
  • ・ソートキーは「ソート済みだから範囲が速い」性質を設計者が選び取るスイッチ

Queryはソートキーに begins_with(前方一致)や between(範囲)を付けられる。整列済みなら開始位置を見つけて隣を読むだけ。

④速さの正体は「局所性」

整列 vs ばらばら
SK順に隣接配置一続きの区間を順になぞる
ばらばらに散在1件ずつ拾い集める
読み方の差
近い場所をまとめ読み
安く速い
個別アクセスの繰り返し
高くつく
  • ・隣り合うデータは一度のアクセスでまとめて取り込める(局所性)

隣接データは一度のアクセスでまとめて取り込める。B木がディスク向けに設計された理由そのものを、主キー設計に持ち込む仕掛け。

⑤別名がそのまま役割を語る

公式の別名と由来
パーティションキー
別名 hash attribute
ソートキー
別名 range attribute
名前の由来=役割
ハッシュで均等に散らす格納先の分散担当
range検索のため整列昇順に近接格納する担当
設計=割り当て作業「どう散らすか」+「どう並べ、どんな範囲で引くか」

hash=散らす担当、range=範囲検索のため整列させる担当。名前の由来から、どの属性に何を選ぶべきかが導ける。

サンプルコード(フレームワーク環境が必要なため表示のみ)

// 複合主キー: Artist(パーティションキー/hash) + SongTitle(ソートキー/range)
// Query は「同じ Artist の項目群(item collection)」の中を、ソートキーで範囲指定して引く

// begins_with: 曲名が "A"〜"K" で始まるもの、のような前方一致
aws dynamodb query --table-name Music \
  --key-condition-expression "Artist = :a AND begins_with(SongTitle, :prefix)" \
  --expression-attribute-values '{":a":{"S":"No One You Know"},":prefix":{"S":"S"}}'

// between: ソートキーが日時などのとき、期間で範囲検索(整列済みなので隣接区間を読むだけ)
aws dynamodb query --table-name Thread \
  --key-condition-expression "ForumName = :f AND LastPostDateTime BETWEEN :start AND :end" \
  --expression-attribute-values '{":f":{"S":"EC2"},":start":{"S":"2015-08-01"},":end":{"S":"2015-11-01"}}'
公式ドキュメントで詳しく ↗