DynamoDBはNoSQLDBとして人気のあるサービスですが、RDBとは考え方が大きく異なるため、初めて使う方は戸惑うことが多いサービスです。
実際にDynamoDBを触って半年経ったので、「最初に知っておけばよかった」と感じたポイントを共有しておきます。
各データの一覧ができるように設計する
DynamoDBでは、RDBのように自由な検索ができるわけではないため、「どういう条件で一覧を取得するのか?」をあらかじめ明確にしておく必要があります。
特に、各データの一覧の取得はシステムの要件になくても開発する上で頻繁に必要になるので最初から設計しておくといいです。
事前に設計するのを忘れても後から追加で取得できるようにはできます。
ただ、緊急でなくても開発しているとどこかで必要になるので、早めに対応しておいた方がいいです。
よく使う〇〇一覧はブックマークしておく
多くの他のAWSサービスでもそうなのですが、DynamoDBもクエリの検索条件はURLに反映されるので、ブックマークしておくと同じ条件で再度開くことができます。
よく確認するデータやクエリ結果の画面は、ブックマークしてすぐ開けるようにしておくと便利です。
DynamoDBはPKとSKで検索を行うのですが、PKとSKを覚えてなくてDB設計書を開いて確認、といった手間がなくなります。
チームでも共有しておくといいです。
最初はオンデマンドで様子を見る
DynamoDBの料金体系には「オンデマンド」と「プロビジョンド」がありますが、最初からプロビジョンドにするのはおすすめしません。
プロビジョンドはWCU/RCUというキャパシティの設計が必要ですが、最適な値は実際に運用してみないと分かりません。
CUの制限に合わせた実装が難しく、たとえば大量のUpdateを行いたいとき、WCUの上限に引っかかる可能性があり、リトライ処理を実装する必要がありますがオンデマンドなら気にする必要がありません。
GSIもそれぞれでCUを設定する必要もあるため、どれくらい必要かわかっていない実運用前に調整するのは難しいです。
また、オンデマンドにすると料金が高いと聞いていたのですが、実際に試しにオンデマンドで運用してみたら、プロビジョンドを使用していたときも安かったので、最初からオンデマンドで開発しておけばよかったです。
クエリで全部取れない問題とlastEvaluatedKeyの罠
DynamoDBでは、QueryやScanで一度に取得できるデータの件数に上限があります(デフォルトで1MB分まで)。
lastEvaluatedKeyを使って、ページングやループ処理でデータを全件取得するような実装が必要です。
本番で動かしたら「一部しかデータが取れてない!」という状態になりかねません。
大抵は全部取得必要があると思うので、lastEvaluatedKeyを考慮した全て取得する関数を作って、それを使うようにしておくといいです。
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { QueryCommand, DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
const client = new DynamoDBClient({});
const ddbDocClient = DynamoDBDocumentClient.from(client);
/**
* DynamoDBのQueryでページネーションを考慮しつつ全件取得する
* @param {object} params - QueryCommandで使うパラメータ(TableName, KeyConditionExpressionなど)
* @returns {Promise<Array>} - 全てのアイテムを含む配列
*/
async function fetchAllItems(params) {
const allItems = [];
let lastEvaluatedKey = undefined;
do {
const command = new QueryCommand({
...params,
ExclusiveStartKey: lastEvaluatedKey,
});
const result = await ddbDocClient.send(command);
if (result.Items) {
allItems.push(...result.Items);
}
lastEvaluatedKey = result.LastEvaluatedKey;
} while (lastEvaluatedKey);
return allItems;
}
バックアップはポイントインタイムリカバリ(PITR)が楽
当初はAWS Backupを利用していましたが、現在はポイントインタイムリカバリ(PITR)を使っています。
テーブル設定で有効化するだけで、秒単位で過去35日間の任意の時点に復元できます。
AWS Backupに比べても料金に大きな差はありません。
バックアップ取得のスケジュール設定やライフサイクル設定をする必要がないので、PITRのほうが運用がシンプルです。
SQLとのデータ取得方法の違い
SQLが使えないので、JOINもできません。
そのため、RDBのような複数テーブルの結合ができないため、複雑なデータの取得はローカルでJavaScriptなどでプログラムを書いてCSVで出力しています。
これは見方によってはメリットでもあるのですが、SQLと違ってプログラムで取得するため自由にデータを取得ができます。
SQLが苦手な人にとってむしろ使いやすいかもしれません。
私も今はこちらの方が使いやすく感じてます。
おわりに
最初から知っておいてたらよかったな〜、と思ったことをまとめました。
これからDynamoDBを使う方に、少しでも役に立てば幸いです。