DynamoDBで実現する柔軟性と高パフォーマンスなデータ管理
株式会社Schoo / 山﨑光都
メンバー / バックエンドエンジニア / 従業員規模: 101名〜300名 / エンジニア組織: 11名〜50名
| 事業形態 |
|---|
B to B B to C |
| 事業形態 | B to B B to C |
|---|
導入の背景・解決したかった問題
導入背景
ツール導入前の課題
Schoo(以下、スクー)では社会人向けの学習コンテンツを配信しており、ユーザーごとに「おすすめ授業」や「人気のコンテンツ」などをパーソナライズして表示します。
この表示ロジックのための集計処理(複数のテーブル結合や、非常に大量のデータ取得を伴う処理)を、当時はページアクセスごとに「RDSから取得 → Webサーバでの処理」という流れで行っていました。しかし、その処理に起因するスロークエリやレイテンシーの悪化が計測されていました。
どのような状態を目指していたか
この集計処理に起因するレイテンシー悪化を改善しUXを向上させるため、ページアクセス時は集計を極力行わずに必要なデータを取得するだけに留め、複雑な処理はバッチ処理などで事前に集計しておく状態を目指しました。
この「事前集計データ」の蓄積先として、DynamoDBの導入を行いました。
比較検討したサービス
- RDS(index追加や集計専用テーブルの配置など、既存構成の最適化)
- Redis
比較した軸
- データ管理におけるパフォーマンス
- データの永続性
選定理由
1桁ミリ秒のパフォーマンス
あらゆる規模で 1 桁ミリ秒のパフォーマンスを実現することを目的として構築されており、100 ユーザーの場合でも 1 億ユーザーの場合でも、アプリケーションで一貫した 1 桁ミリ秒のパフォーマンスを出せる。 https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Introduction.html
Redisとの使い分け
スクーでは、以下のように使い分けています。
DynamoDB: データの永続性が必要で、かつ整合性を保ちたいデータ -(例:ランキング集計データ、ブックマーク数など、RDSを元にした集計データ)
- 特に「RDSから取得してWebサーバーで都度集計する」と処理が重くなるような、事前集計データの保存先として利用
Redis: 揮発してしまっても(消えても)問題ない一時的なデータ
導入の成果
- 事前集計データのキャッシュ先として導入したことで、集計処理に起因するレイテンシーの悪化を改善
導入に向けた社内への説明
上長・チームへの説明
- サービスの仕様や目指す非機能要件(パフォーマンス、可用性など)を実現できるか
- データを永続的に保存する必要があるか
- リアルタイム性をどの程度要求するか
など、スクーが実現したいこと・目指す姿を実現できるかをチームで議論しました。
活用方法
基本的な構成
「ツール導入前の課題」で挙げたような集計処理をバッチで実行し、その集計結果をDynamoDBに保存する構成にしています。アプリケーション(Webサーバー)は、都度集計を行うのではなく、DynamoDBに保存された事前集計データを参照します。
スキーマ設計
DynamoDBでは、すべてのデータを1つのテーブルに格納する「単一テーブル設計」がベストプラクティスとして知られています。(1アプリに対して1テーブル) スクーでも単一テーブル設計を意識しています。
この設計のポイントは以下になります。
- データ構造よりも「アクセスパターン」を中心に考える
- NoSQL データベースでは、SQL のようなクエリの柔軟性が低いため、スキーマを構築する前に、アプリケーションが必要とするデータアクセスパターン(読み取り、書き込み、集計など)を明確に特定することが重要
- 1テーブルに異なる種類のエンティティ(例:授業、ユーザー、ランキング)を共存させ、RDBのようにエンティティごとにテーブルを分けるのではなく、「必要なアクセスが効率的にできる構造か?」を最優先する
単一テーブル設計のメリット
- 関連する複数の種類のデータを一度のQuery操作で効率的に取得できる
- 先程注意点として挙げた通り、DynamoDBでは複数のテーブルをJOINすることなどができないですが、単一テーブル設計とし、同じパーテーショーンキーを付与することで1回のQuery操作で取得することができる
ex.)コンテンツとお気に入り数をDynamoDBで管理しているケース。これが2つのテーブルに分かれていると2回Queryを実行することになる
PK(Partition Key) | SK(Sort Key) | 属性1 | 属性2 | 属性3 |
|---|---|---|---|---|
content#123 | content_details | content | DynamoDB入門 | |
content#123 | bookmark_count | count | 10 | |
content#456 | content_details | content | AWS入門 | |
content#456 | bookmark_count | count | 5 |
- オペレーション負担が軽減される
- 複数のDynamoDBテーブルがあると、設定、監視、バックアップなどをそれぞれのテーブルに対して行うことになり複雑になってしまう
ただ、必ずしも単一テーブル設計が優れているわけではありません。ユースケースを考え単一テーブル設計と複数テーブル設計を選択するのが大切になります。
よく使う機能
- Secondary Indexes
- GSIを効果的に設定することで、効率的に複数のデータ取得パターンを実現することができる
GSIについては以下の記事でまとめていますのでよろしければご確認ください。 https://qiita.com/hiroto_0411/items/ea98e9a72e13b0658c18
ツールの良い点
- Key-Value + ドキュメントモデル
- さまざまなユースケースをサポートするために、key-value モデルとドキュメントデータモデルの両方をサポートしている
- サーバーレス
- サーバーレスであり、ソフトウェアの管理、インストール、保守、運用は必要なく、バージョンも気にしなくて良い
- 1桁ミリ秒のパフォーマンス
- あらゆる規模で 1 桁ミリ秒のパフォーマンスを実現することを目的として構築されており、100 ユーザーの場合でも 1 億ユーザーの場合でも、アプリケーションで一貫した 1 桁ミリ秒のパフォーマンスを出せる
ツールの課題点
- クエリの自由度が低い
- SQLのような複雑なクエリ(JOIN、GROUP BY、IN、サブクエリなど)は使えない
- 事前にアクセスパターンを予測して、GSIやLSIを適切に設計する必要がある
- テーブル設計の考え方がRDBとは違うため、慣れる必要がある
- アクセスパターンに基づいた考え方が必要
- トランザクションは不得意
- トランザクションAPI(TransactWriteItemsなど)はありトランザクションを実現することはできるが、制限が多く処理も高コスト
ツールを検討されている方へ
柔軟性と高パフォーマンスを必要とするデータを管理したいとき、DynamoDBは強力な選択肢の1つになると思います。
ただし、上記に挙げた通り、RDBとは違ったDynamoDB特有の特徴や思想(特にアクセスパターン中心の設計)があります。自分たちが実現したい要件(データの永続性は必要か、クエリのパターンは事前に予測可能か、トランザクションは必須かなど)を明確にし、その要件を満たしているかを確認することが非常に大切だと思います。
株式会社Schoo / 山﨑光都
メンバー / バックエンドエンジニア / 従業員規模: 101名〜300名 / エンジニア組織: 11名〜50名
2024年に新卒として株式会社Schooに入社。バックエンドエンジニアとしてシステムリプレイスを行うチームに所属。また、テックブログの立ち上げ、イベントの主催など技術広報活動も担当。 現在はデザインシステムプロジェクトのリーダーも兼務。
よく見られているレビュー
株式会社Schoo / 山﨑光都
メンバー / バックエンドエンジニア / 従業員規模: 101名〜300名 / エンジニア組織: 11名〜50名
2024年に新卒として株式会社Schoo...
レビューしているツール
目次
- 導入の背景・解決したかった問題
- 活用方法


