最近、メインの RDBMS にすべてのテーブルを入れている構成について、「これ、ちょっと重くないか?」という話が出ました。特に監査ログのように書き込みが多く、参照も限定的なデータは、別のストレージに分けたほうがいいのではないか、という流れです。
その候補として名前が挙がったのが DynamoDB でした。
ただ、自分はこれまでずっと RDBMS 前提で設計してきました。DynamoDB も触ったことはありますが、思想レベルでちゃんと理解しているかと言われると怪しい。
DynamoDB は RDBMS の代替ではありません。同じ「テーブル」という言葉を使いますが、考え方がまったく違います。 RDBMS は後から自由に検索できる前提です。一方、DynamoDB はアクセスパターンを先に決めておく前提です。
この違いを曖昧なまま進めると、どこかで設計が破綻します。
なので一度、自分の頭を整理する意味も込めて、RDBMS と比較しながら DynamoDB の制約と設計思想をまとめてみます。
DynamoDBの基本的な位置付け
DynamoDB は分散キーバリューストアです。
- SQL なし
- JOIN なし
- GROUP BY なし
- 任意条件検索不可
「テーブル」という名称に引きずられると誤解しやすいですが、 RDBMS のクエリエンジンとは別物です。
主キー設計の違い
自動インクリメントIDは存在しません
RDBMS の AUTO_INCREMENT のような機能はありません。 主キーはアプリケーション側で設計・生成します。
Partition Key(PK)は必須です
- PK は必須
- SK は任意(実務上ほぼ必須)
RDBMS の主キーは一意性担保のための識別子です。 DynamoDB の PK はデータ分散単位です。
PKは偏りを避ける設計が必要です
- 均等分散が前提
- 偏り=ホットパーティション
- スロットリングの原因
例:
created_atを PK にする設計- 日付のみを PK にする設計
同時刻帯アクセス集中により負荷が偏ります。
PKを指定しない検索はできません
- PK 未指定 Query 不可
- PK 未指定は Scan
RDBMS の WHERE 検索とは根本的に異なります。
Query と Scan の制約
Query の制約
- PK 指定必須
- PK は固定値のみ
- PK に対する範囲条件不可
- 範囲検索は SK のみ
- OR 条件不可
- 複数 PK 同時検索不可
Query は「PK = 固定値」の範囲内検索です。
FilterExpression の性質
- 読み取り後に絞り込み
- 読み取りコスト削減効果なし
RDBMS の WHERE 句とは性質が異なります。
Scan の特性
- 全件読み取り
- データ量比例でコスト増加
- Scan + Filter = 全件読んでから絞り込み
Scan 前提設計は高コストです。
インデックス(GSI / LSI)
インデックスは事前設計前提
- GSI は独立インデックス空間
- GSI でも PK 指定必須
- 1回の Query で使用可能なインデックスは1つ
- GSI 横断検索不可
RDBMS のインデックスとは性質が異なります。
GSI の制約
- 後から追加可能(構築時間あり)
- 削除もコスト発生
- Projection 外属性は取得不可
- 書き込み時に本体 + GSI 分の課金
JOIN と関連取得
- JOIN 不可
- テーブル横断検索不可
- 正規化前提設計不可
関連データ設計方法:
- 同一アイテム内格納
- 同一 PK に集約
集計・分析機能
- COUNT / SUM / GROUP BY なし
- 条件付き件数取得不可
- 全件 Scan → アプリ集計
- 大量データのリアルタイム集計は非現実的
集計が必要な場合は事前集計テーブル設計が必要です。
並び順とソート
- ORDER BY なし
- 並び順は SK 依存
- SK 以外でのソート不可
- 複数キーソート不可
ソートは物理並び順設計です。
トランザクションと整合性
- トランザクション最大 25 アイテム
- 外部キー制約なし
- カスケードなし
- 整合性保証はアプリ責任
データサイズ制限
- 1 アイテム最大 400KB
- 属性サイズ制限あり
- 不要属性も読み取りサイズ対象
サイズはコストに直結します。
ページングと取得制限
- 1 回の Query / Scan 最大 1MB
- LIMIT = 読み取り上限
- OFFSET なし
- ページ番号指定不可
- ExclusiveStartKey 方式
パフォーマンスと課金
- 読み取りサイズ = 課金単位
- Scan は高コスト
- ホットパーティション = スロットリング要因
- GSI 書き込みは追加課金
- キャパシティ不足時はエラー
パフォーマンスとコストは直結します。
設計変更の難易度
- PK / SK 変更不可
- キー変更 = 全件再投入
- アクセスパターン変更 = 設計再構築
柔軟性は高くありません。
事前に決定すべき事項
- 想定 Query 一覧
- PK / SK 設計
- 必要な GSI
- 想定最大データ量
- 1 クエリ返却単位
- 集計要否
アクセスパターン確定が最優先です。
避けるべき設計
- PK を単純連番にする設計
- 日付のみを PK にする設計
- Scan 前提設計
- FilterExpression を WHERE と誤認
- GSI 後付け前提設計
結論
RDBMS は柔軟検索前提です。 DynamoDB はアクセスパターン固定前提です。
両者は目的が異なります。
DynamoDB を利用する場合は、 データ構造よりも先にアクセスパターンを確定させる必要があります。