DynamoDBについてとその設計
はじめに
DynamoDBの設計について、まず言いたいのが 「アクセスパターンがわからないのにテーブルを作るな」 です。
スキーマレスだからといって全く設計がいらないわけではありません。
なんならただのSQLのテーブル設計は正規化手順のもと機械的に設計すればいいぶん、DynamoDBのほうが面倒と言ってもいいと思います。
基本
DynamoDBのテーブルの要素について、PartitionKeyとSortKey、その他ただの要素で構成されます。
PartitionKeyとその他要素で作る、もしくはPartitionKey+SortKeyとその他要素で作ることができます。
その際、PartitionKey1つで一意に定まる、もしくはPartitionKey+SortKeyの2つで一意に定まるようにしなければなりません。
SQLでいう複合主キーで3つ以上の要素を設定するなどといったことはできません。
また、検索する際にPartitionKeyのみ、もしくはPartitionKey+SortKeyで検索することができますが、SortKeyを設定している状態でPartitionKeyのみで検索を行うとPartitionKeyが一致する全ての要素を検索できます。
PartitionKeyに対して可能な検索方法は完全一致のみです。
SortKeyに対して可能な検索方法は、EQ、LE、LT、GE、GT、BEGINS_WITH、BETWEENです。
日本語にすれば、完全一致、より小さい、より大きいい、以下、以上、X~Y、~で始まる、です。
table: query
設定 可能なクエリ
PartitionKeyのみ PartitionKey検索のみ
PartitionKey+SortKey PartitionKey検索
PartitionKey検索かつSortKey検索
さらに、キー(PartitionKey、SortKey)に設定できる型は以下の3つしかありません。
- S — 文字列
- N — 数値
- B — バイナリ
非キー要素には以下の型が設定できます。
- S — 文字列
- N — 数値
- B — バイナリ
- BOOL — ブール
- NULL — Null
- M — マップ
- L — リスト
- SS — 文字列セット
- NS — 数値セット
- BS — バイナリセット
非キー要素にも検索する機能は提供されてはいますが、PartitionKeyで検索した後に取得できた値に対してフィルターをするのみで、実際にテーブルから効率的に検索できているわけではないことに留意してください。以下の方法でフィルターできます。
- attribute_type(value)
- begins_with(value)
- between(low_value, high_value)
- contains(value)
- eq(value)
- exists()
- gt(value)
- gte(value)
- is_in(value)
- lt(value)
- lte(value)
- ne(value)
- not_exists()
- size()
セカンダリーインデックス
さて、これまで説明した要素のみで設計するのは、制限が多すぎてまず無理です。
これを解決するためにローカルセカンダリーインデックスとグローバルセカンダリーインデックスがあります。
グローバルセカンダリーインデックス(GSI)について
PartitionKey と SortKey を別に新しく設定できます。ただし、以下の制限があります。
1 つのテーブルにつき 20 個まで設定可能
テーブル構築後に後から追加で設定できる
実質テーブルを複製するようなものなのでコストはその分増加する
ローカルセカンダリーインデックス(LSI)について
パーティションキーをそのままに SortKey を別のものに設定できるものです。ただし以下の制限があります。
テーブルの初回構築時にしか設定できない
1 つのテーブルにつき、最大 5 個までしか設定できない
GSIほどではないが、コストは増加する
ユースケース(クエリ方法)から設計する
紹介したようにDynamoDBにはクエリ方法にかなりの制限があります。
詳細は公式を見て頂くとして、
設計するにあたっての注意点です。
PartitionKeyは物理的なデータ格納場所が分けられているため、PartitionKeyが全てバラバラなユニークIDなどが設定されている場合、GSIでまたがったデータをクエリすると非常に遅くなることがある。
複数テーブルを用意して正規化するような設計はDynamoDBには一切向かない
SortKeyに「~#~」のように設定して階層構造を表すことがよくある。
データが重複している部分があっても構わない。むしろ推奨されることがある。
ユースケースからどう設計すれば必要なクエリが可能かを考え、設計する。
想定される追加のユースケースについては、属性が後からいくらでも追加できることを利用する。
2024-03-23追記 更新中
料金体系はプロビジョンドとオンデマンドの2種類
プロビジョンド
バーストキャパシティ
Auto Scaling
各操作によって消費されるWCU、RCU
GSI、LSIによる消費倍化
オンデマンド
各操作によって消費されるWRU、RRU
GSI、LSIによる消費倍化