DynamoDBのテーブル構造や設計について、特にRDBと違う点を中心に
最近DynamoDBを使う機会があったのでキーワード毎にゆるくまとめたい
キーワード:Query/Scan、GSI/LSI、パーティションとソートキー、HashとRange
キーワードごとのまとめ
Query/Scan
- Query:プライマリキーの値に基づいて項目を探す操作、RDBで言うとインデックスが設定されたテーブルでのクエリ
- Scan:全件取得なのでパフォーマンスはQueryに比べると悪い
- Scanはクライアント側でフィルタせず、DynamDB側でfilter処理させることも可能だが内部でのレコードの取得はやっぱり全件らしい
- なので、設計時にQueryが実行できるようにすべきでScanは仕方なく使う感じになるのかな?
Queryはプライマリーキーに対してしか実行できない。結構不便と思うかもしれないがGSI/LSIを設定することでQueryを実行できるフィールドを増やせる。
具体的にどのようなプライマリーキーやGSI/LSIがあるのかは後述。
GSI/LSI
Global secondary index(GSI) は既存のテーブルに追加することが可能、一方で local secondary index(LSI)はテーブルの作成時のみに作成が可能。
となれば全部GSIでいいじゃんという気もしますね。
プライマリーキーやGSI/LSIで何が追加できるのか?
Amazon DynamoDB のコアコンポーネント - Amazon DynamoDB
DynamoDB は 2 種類の異なるプライマリキーの持ち方をサポートする
DynamoDBの内部的にはこのパーティションキー=Hash、ソートキー=Rangeで定義されているようなのだが、この名称になった由来などが探しても見つからない。
以降はHash, Rangeという用語で文章を記載する。
くどいけど言い換えよう。DynamoDB は 2 種類の異なるプライマリキーの持ち方をサポートする
- (1) Hashだけ
- (2) HashとRange
キーの指定はHashは完全一致(EQ)のみだが、Rangeは名前の通りEQ | LE | LT | GE | GT | BEGINS_WITH | BETWEENのような範囲を指定できる(※ただしもちろんHashを指定した上で!)
KeyConditions - Amazon DynamoDB
ruby - Querying DynamoDB table by hash and range key - Stack Overflow
このへんですでに条件がややこしい。
注意
① Hashキーとは言え、キーを指定したら必ず1件返るわけではない。データによっては複数件返る。Hashというと連想配列を想像しがちだが、DynamoDBのそれはキーに対してオブジェクト(配列を含む)を返すイメージだ
② Hash+Rangeキーが設定されたプライマリーキーのあるテーブルの場合、Rangeキーのみで検索できない *1
③ RDBであればWHERE句を使えばどのカラムからでも検索可能だが、DynamoDBだと効率の良い検索をしようと思えば事前にプライマリーキーやGSIをよく考えておく必要がある
GSIの挙動
- 追加のときの挙動
- 要は、RDBのALTER TABLEみたいな感じでGSIを追加できるということが書きたい
- グローバルセカンダリインデックスの管理 - Amazon DynamoDB
リソース割り当てフェーズとバックフィルフェーズの進行中、インデックスは CREATING 状態になっています。この間、DynamoDB はテーブルに対して読み込みオペレーションを実行します。グローバルセカンダリインデックスを設定するためのベーステーブルからの読み込みオペレーションに対しては課金されません。ただし、新しく作成されたグローバルセカンダリインデックスを設定するための書き込みオペレーションに対しては課金されます。
インデックス構築が完了すると、ステータスは ACTIVE に変わります。インデックスが ACTIVE になるまで、Query や Scan はできません。
残り、dynamodb-local+dynamodb-adminでのローカルでの検証とかも書こうと思ったが力尽きたのでこのへんで終了。