サーバーレスデータベース徹底比較:DynamoDB vs Firestore vs MongoDB vs Cassandra vs Redis vs FaunaDB
はじめに
本記事は、2021年4月に公開したブログ記事の続編です。
私たちは、一般的なWebユースケースとサーバーレス関数を用いて、主要なサーバーレスデータベースのパフォーマンスを比較するサンプルアプリケーションを構築しました。比較対象は、DynamoDB、MongoDB(Atlas)、Firestore、Cassandra(Datastax Astra)、FaunaDB、Redis(Upstash)の6つです。
アプリケーションおよびソースコードは公開しているので、ぜひご確認ください。
測定内容と方法
今回比較したのは、各データベースで上位10件のニュース記事を取得する際のレイテンシです。使用したデータは、New York Times APIから収集した実在のニュース記事7,001件です。測定対象のクエリは以下の通りです。
select * from news where section = "World" order by view_count desc limit 10
バックエンドはAWS Lambda上のサーバーレス関数として実装しています(FirestoreのみGoogle Cloud Functionsを使用)。可能な限り、サーバーレス関数とデータベースを同じリージョンに配置し、レイテンシを最小化しました。
レイテンシの測定では、データベースへの接続時間を除外し、クエリ実行直前と直後のタイムスタンプを記録しています。測定はバックエンド(サーバーレス関数内)で行われるため、ブラウザとサーバー間のネットワークレイテンシは含まれず、サーバーレス関数のコールドスタート時間の影響も受けません。
さらに、動的な実世界のデータをシミュレートするため、上位10件の記事には毎回ランダムなview_count値を割り当てています。これにより、毎回異なる記事セットを強制的に返させ、データベース側のキャッシュ利用を防止しています。なお、更新操作はレイテンシの計算には含まれていません。
測定結果
以下は、本日時点(8月25日)のレイテンシ数値です。

各データベースのカスタム設定
次に、各データベースに適用した個別の設定を紹介します。
DynamoDB
- リージョン:US-West-1
- 読み書きキャパシティ:50(デフォルト値は5)
- インデックス:パーティションキー「section(String)」、ソートキー「view_count(Number)」を持つGSI
- 備考:クライアントがすでに同じリージョン(US-West-1)にあるため、グローバルテーブルは有効化していません
コードはこちらからご覧いただけます。
MongoDB(Atlas)
- リージョン:AWS N. Virginia(us-east-1)
- クラスタティア:M5(General)
- インデックス:「section」と「view_count」の複合インデックス
- 備考:MongoDBのサーバーレス版も試したかったのですが、Node.jsドライバーが提供されていませんでした。ただし、DB接続処理をレイテンシ計算の対象外にしているため、実質的な問題にはなりません。
コードはこちらからご覧いただけます。
Firestore
- リージョン:GCP US-Central
- モード:Datastore
- インデックス:「section(昇順)」と「view_count(降順)」の複合インデックス
コードはこちらからご覧いただけます。
Cassandra(Datastax Astra)
- リージョン:AWS US-East-1
- プラン:従量課金(Pay as you go)
- インデックス:PRIMARY KEY(section, view_count, id)
- API:REST API
コードはこちらからご覧いただけます。
FaunaDB
- プラン:Individual(月額25ドル)
- インデックス:term=section、value=view_count
- API:FQL
コードはこちらからご覧いただけます。
Redis(Upstash)
- リージョン:AWS US-West-1
- プラン:従量課金(Pay as you go)
- インデックス:SortedSetを使用
- 備考:シングルゾーンとマルチゾーンのデータベースをそれぞれ別々にテストしています
コードはこちらからご覧いただけます。
特記事項
- FaunaDBについて:デフォルトでより強力な整合性保証とグローバルレプリケーションを提供します。一方で、デプロイ先のリージョンを選択できません。これらが相対的に低いパフォーマンスの一因である可能性があります。
- Firestoreについて:他のデータベースと同程度のパフォーマンスを示しますが、ばらつきが大きめです。コールドコネクションのオーバーヘッドが原因かもしれません。接続を維持し続ける方法が見つけられなかったため、良いアイデアがあればぜひお知らせください。
- Cassandraについて:主キーフィールドの更新が許可されていません。また、頻繁に更新されるカラムに対してセカンダリインデックスは非推奨のため、view_countを更新できませんでした。本来ならこの更新はパフォーマンスに有利に働くはずだった点にご留意ください。
- Upstash(Redis)について:シングルゾーンの方がわずかに速く見えますが、シングルゾーンとマルチゾーンの間に大きな性能差はありません。また、REST APIは高いパーセンタイルにおいてネイティブAPIと非常に近いパフォーマンスを示しています。
まとめ
このベンチマークは継続的な取り組みであり、品質向上のために今後もコードのリファクタリングを行っていきます。特定の製品のコードをリファクタリングした際は、そのヒストグラムをリセットします。コードをご確認いただき、改善点があればぜひお知らせください。TwitterやDiscordからご連絡いただけます。
-
サーバーレスデータベースのレイテンシー徹底比較:DynamoDB vs FaunaDB vs Upstash
はじめに本記事では、典型的なWebアプリケーションのユースケースを想定し、3つのサーバーレスデータベース——DynamoDB、FaunaDB、Upstash(Redis)——のレイテンシーを実測データに基づいて比較します。検証のためにニュースサイトのサンプルを構築し、サイトへの各リクエスト時にデータベース関連のレイテンシーを記録する仕組みを実装しました。実際のサイトとソースコードは公開しているので、興味のある方はぜひ参照してください。各データベースには、New York Times Archive APIから収集した7,001件の記事(2021年1月分の全記事)を挿入済みです。さらに、各記事に
-
Redis LSETコマンドの使い方 – リストの指定インデックスに要素を設定する方法
このチュートリアルでは、Redisデータストアに保存されたリスト型の値に対して、新しい要素を設定する方法を解説します。そのために使用するのが、RedisのLSETコマンドです。 LSETコマンドとは LSETコマンドは、キーに保存されているリスト型の値に対して、指定したインデックスの位置にある要素を新しい値で上書きします。 インデックスはゼロベースで扱われます。つまり、「0」が先頭の要素、「1」が2番目の要素というように対応しています。また、負の数を使うことも可能で、「-1」は末尾の要素、「-2」は末尾から2番目の要素を意味します。 なお、範囲外のインデックスを指定してLSETコマンドを実行す