複雑なクエリが必要になる場合はDynamoDBは向いていない、と言うのはよく聞くが、具体的にどういう場合かをまとめる。
モチベーション
最近ではAmplifyを使用する人が増えて、そのチュートリアルやデフォルトでDynamoDBが使用されているのでなんとなく使っている人も多いと思うが、実用的なサービスにおいてDynamoDBだけで十分というケースは少ないのではないかと思う。
DynamoDBを使用する場合は本当にそれで良いのか検証しておかないと、開発が進んでからRDBに置き換えて、アーキテクチャの大きな変更を余儀なくされるという大変な事態になりかない。
DynamoDBを使わないほうが良い場合
- SQLにおけるWHERE句を2つより多く使う様な検索が必要になる場合
- 25個以上のアイテムを同時(アトミック)に更新する必要がある場合
- 検索と更新を同時に実施したい場合。例えば、SQLだと
UPDATE ... WHERE ...
のような、検索して複数のアイテムを一括更新したい場合。DynamoDBではできない。
下記にこの根拠となる制限を説明する。
DynamoDBの制限
1度の検索に利用できるフィールドは(パーティションキーとソートーキーの)2つまで
なので、SQLにおけるWHERE句を2つより多く使う様な検索ができない。
DyanmoDBはあくまでKey-Valueストアなので、キーでしか検索できない。
2つのフィールドまで対応できるのは、2つのフィールドを指定してセカンダリインデックスを作成した場合で、セカンダリインデックスとは2つのフィールドを組み合わせた文字列をKeyとしたKey-Valueストアの複製を作っているだけなので、キーでしか検索できないことには変わりがない。
(Amplifyでは複数のソートキーを指定できるが、裏側で複数のフィールドの値を連結して1つのソートキーフィールドとしているだけなので、1つ目のソートキーは使用しないとかはできない。)
25個を超えるアイテムをアトミックに更新できない
それがDyanmoDBの仕様なので、25個を超えるアイテムをアトミックに更新したい場合はDyanmoDBでは対応しきれない。
検索と更新を1クエリでできない
DynanmoDBは一旦検索をしてその結果を元に最大25個ずつの更新(良くて最大25個の同時更新)になる。
DynamoDBはKey-Valueストアであり、あくまでkeyでしかデータを検索できないので、データの更新には必ずkeyを指定する必要がある。なので、UPDATE ... WHERE ...
のようにkey以外のフィールドで抽出して同時に更新すると言うことはできない。
つまり、データをDynamoDBで取得してから、それらを更新するリクエストを投げる必要がある。
その他の制限
- 複雑な検索にはElasticSearch (@searchable アノテーション)が利用できるが、複数テーブルを利用した検索はできない(例えば、ユーザのリソース権限のテーブルとリソーステーブルのステータスの両方を使用した検索は対応できない)
- グローバルセカンダリインデックス(GSI)は1テーブルに20個まで(クオータ追加のリクエストはできる)。テーブル作成後でも追加・削除でき自動でバックフィルしてくれる。
- ローカルセカンダリインデックス(LSI)は1テーブルに5個までで。テーブル作成時にしか作成できない。
DynamoDBを使うモチベーション
これだけだとDynamoDBの悪口を書いただけの様になってしまうので、DynamoDBが活躍できるケースも書いておく。
- チャットのメッセージデータのようにアイテム(SQLにおけるrow)数が膨大でもデータを高速に取得したい。
- Amplifyにバックエンドの実装を丸投げしたい(Amplifyがやってくれないものは諦める)。
- AmplifyでのRDSの利用には知識と一手間が必要なので、DynamoDBでできる範囲で妥協する。
- DynamoDBのストリーミング(追加や更新などを通知する仕組み)機能を利用したい。
- サーバレス構成でインスタンスの管理の手間を無くしたい。
(現在では、RDSもAurora Serverless v2がリリースされたのでcold start問題なども解消されて、RDSサーバレスも実用レベルかもしれない。)
以上、DynamoDBを使おうか検討している人のお役に立てれば幸いです。