DynamoDB カンニングペーパー

2025年3月24日

このカンニングペーパーの使い方

このカンニングペーパーではDynamoDBの基本から実践的な使い方まで、コンパクトにまとめています。困った時に参照してください。専門用語には太字で印をつけてあります。

DynamoDBの基本:そもそも何者?

DynamoDBとは?

  • AWSが提供するNoSQLデータベース
  • 従来のRDB(MySQL, PostgreSQLなど)と違い、テーブル間の関連性より「速さ」と「スケーラビリティ」を重視
  • フルマネージド型(運用の手間が少ない)
  • ミリ秒単位の応答速度が特徴

RDBとの主な違い

項目 RDB (例:RDS) DynamoDB
データモデル 正規化されたテーブル、固定スキーマ スキーマレス、柔軟な構造
クエリ言語 SQL 専用API (SQLなし)
スケーリング 垂直スケーリング 水平スケーリング
設計アプローチ スキーマ先行設計 アクセスパターン先行設計
得意分野 複雑なJOIN、複雑なクエリ シンプルな読み書きの高速処理

基本的な構造

  • テーブル:データの箱。例えば「ユーザーテーブル」「商品テーブル」。
  • アイテム:テーブル内の1レコード。例えば「ユーザーテーブル内の田中さんのデータ」。
  • 属性:アイテムが持つ情報。例えば「名前」「年齢」「メールアドレス」。
// ユーザーテーブルのアイテム例 { "user_id": "123", "name": "田中太郎", "email": "tanaka@example.com", "age": 28, "preferences": { "theme": "dark", "notifications": true }, "last_login": "2025-03-20T10:30:00Z" }

キホンのキ:キーの理解

キーの種類

  • プライマリキー:必須。以下の2種類がある
    • パーティションキーのみ:単一キー構成
    • パーティションキー + ソートキー:複合キー構成

パーティションキーとは?

  • データがどの区画(パーティション)に保存されるかを決める値
  • 例えば「user_id」「product_id」など
  • 均等に分散する値を選ぶとパフォーマンスが向上
👉 ホットパーティション問題:特定のパーティションにアクセスが集中すると性能低下

ソートキーとは?

  • 同じパーティション内でのデータの並び順を決める値
  • 例えば「登録日」「注文ID」など
  • 範囲検索(○○以上××以下)も可能
  • パーティションキーとセットで一意になるように設計
パーティションキー:user_id = "123" ソートキー:timestamp = "2025-03-01T..." 〜 "2025-03-31T..." → 3月の全注文履歴が取得できる

データの取り出し方

クエリ操作

  • 特定のパーティションキーに対してデータを取得
  • 効率が良く、高速
  • ソートキーがある場合は、その範囲や条件での絞り込みも可能
// JavaScriptでの例 const params = { TableName: "Users", KeyConditionExpression: "user_id = :uid", ExpressionAttributeValues: { ":uid": "123" } }; await dynamodb.query(params).promise();

スキャン操作

  • テーブル全体を一つずつ確認する方法
  • データが多いとめっちゃ時間かかるしコストもかかる
  • できるだけ避けるべき操作
// JavaScriptでの例 (非推奨) const params = { TableName: "Users", FilterExpression: "age > :min_age", ExpressionAttributeValues: { ":min_age": 20 } }; await dynamodb.scan(params).promise();

インデックスで検索を効率化

グローバルセカンダリインデックス (GSI)

  • パーティションキーとは別の属性でデータを探せるようにする
  • 例:ユーザーIDではなく、メールアドレスからユーザーを探したい
  • テーブル作成後でも追加・変更・削除可能
// メールアドレスからユーザーを検索する例 const params = { TableName: "Users", IndexName: "email-index", KeyConditionExpression: "email = :email", ExpressionAttributeValues: { ":email": "tanaka@example.com" } }; await dynamodb.query(params).promise();

ローカルセカンダリインデックス (LSI)

  • 同じパーティションキーだけど、別のソートキーでデータを探せるようにする
  • テーブル作成時にしか設定できない
  • 使用頻度はGSIより少ない

キャパシティ設定:DynamoDBの処理能力

プロビジョンドモード

  • 1秒間に何回読み書きできるかを事前に設定
  • RCU(読み取りキャパシティユニット)とWCU(書き込みキャパシティユニット)で設定
  • 予測可能なトラフィックに最適
  • 自動スケーリングと組み合わせて使うのが一般的

オンデマンドモード

  • 使った分だけ支払う方式
  • 急なアクセス増加にも自動対応
  • トラフィック予測が難しい場合に便利
  • ただし、長期的にはプロビジョンドより高くなりがち

💰 コスト比較ヒント

  • スタートアップフェーズ → オンデマンド(柔軟性重視)
  • 安定フェーズ → プロビジョンド + 自動スケーリング(コスト最適化)
  • 一時的な大量アクセスがある場合 → イベント前にプロビジョンドの容量増強

便利な追加機能

TTL(Time To Live)- データの賞味期限設定

  • データに有効期限をつけて自動削除
  • セッション情報や一時データに最適
  • バックアップコストの削減にも効果的
// TTLの例:24時間後に削除される一時トークン { "token_id": "abc123", "token_value": "xyz789", "user_id": "123", "expiration": 1711392000 // Unix時間 }

DAX(DynamoDB Accelerator)

  • インメモリキャッシュでめっちゃ高速化(マイクロ秒単位)
  • 読み取りの多いワークロードに有効
  • 実装は簡単(SDK差し替えるだけ)

トランザクション

  • 複数の操作を一括で実行(全部成功か全部失敗か)
  • 例:在庫減らす+注文確定など
  • RDBMSのACID特性に近い安全性

ストリーム

  • テーブルの変更をリアルタイムで捕捉
  • Lambda関数との連携で様々な自動処理が可能
  • 例:注文テーブル更新→自動メール送信

グローバルテーブル

  • 世界中の複数リージョンにデータを自動複製
  • 低レイテンシーのグローバルアプリに最適
  • マルチリージョン障害対策にも

DynamoDBの設計アプローチ(超重要)

RDBとDynamoDBの設計思想の違い

RDB
「データをどう保存するか」から考える
DynamoDB
「データをどう取り出すか」から考える

設計ステップ

設計の流れ
  1. アクセスパターンを洗い出す(どんなクエリが必要か全部リストアップ)
  2. キー構造を設計(パーティションキー、ソートキー)
  3. 必要なインデックスを計画(GSI、LSI)
  4. 非正規化を検討(JOIN操作がないので、データを複製することも)

DynamoDBの設計パターン

シングルテーブルデザイン

  • 複数のエンティティを1つのテーブルに格納
  • PKとSKの組み合わせでエンティティを区別
  • 一見複雑だが、パフォーマンスが高く、JOINが不要に
// ユーザーアイテム { "PK": "USER#123", "SK": "PROFILE", "name": "田中太郎", "email": "tanaka@example.com" } // 同じユーザーの注文アイテム { "PK": "USER#123", "SK": "ORDER#456", "orderDate": "2025-03-24", "amount": 5000 }

GSIオーバーロード

  • 1つのGSIを複数の用途で利用
  • データ属性を使い分けることで様々なクエリを実現
// GSI1-PK と GSI1-SK を複数の用途で使い回す // 例: 商品検索用 { "PK": "PRODUCT#789", "SK": "METADATA", "name": "ゲーミングPC", "GSI1-PK": "CATEGORY#electronics", "GSI1-SK": "PRODUCT#ゲーミングPC" } // 例: メール検索用 { "PK": "USER#123", "SK": "PROFILE", "name": "田中太郎", "email": "tanaka@example.com", "GSI1-PK": "EMAIL#tanaka@example.com", "GSI1-SK": "USER#123" }

DynamoDB vs RDS 選択ガイド

DynamoDBが最適なケース

  • 高いスケーラビリティが必要
  • シンプルなキーバリュー検索が中心
  • 低レイテンシーが絶対条件
  • サーバーレスアーキテクチャとの連携
DynamoDBが向いている例: セッション管理、ユーザープロファイル、ゲームのスコアボード、IoTデータの収集、リアルタイムダッシュボード

RDSが最適なケース

  • 複雑なJOINクエリが必要
  • トランザクション整合性が重要
  • 複雑な分析や集計が必要
  • SQLの専門知識を持つチームがある
RDSが向いている例: 財務システム、複雑な検索が必要なECサイト、BI/分析システム、複雑なレポート生成システム

コスト最適化のコツ

DynamoDBのコスト要素

  • 読み取り/書き込みキャパシティ
  • ストレージ量
  • データ転送量
  • バックアップと追加機能

コスト削減テクニック

  • 適切なキャパシティモードの選択
  • 自動スケーリングの設定(プロビジョンドの場合)
  • 不要なGSIの削除(GSIもコストがかかる)
  • TTLで不要データを自動削除
  • 大量読み取りにはDAXの検討

よくあるトラブルと対策

ホットパーティション問題

  • 特定のパーティションに負荷が集中する問題
  • 対策:パーティションキーの再設計、ハッシュ接尾辞の追加など
// 不均一なアクセスを分散させる例 // user_id + 乱数 でパーティションキーを作成 const randomSuffix = Math.floor(Math.random() * 10); const partitionKey = `${userId}_${randomSuffix}`;

スロットリング(リクエスト制限)

  • キャパシティを超過するとリクエストが拒否される
  • 対策:指数バックオフ&リトライ、キャパシティ増強

スキャン操作の非効率性

  • 全テーブルスキャンは避ける
  • 対策:パラレルスキャン、ページネーション、GSIの活用

DynamoDBを使うときの実践的なTips

開発環境のセットアップ

  • ローカル開発には「DynamoDB Local」を使える
  • AWS CLIとDynamoDB管理ツール(NoSQL Workbench)の活用

データのバックアップ

  • オンデマンドバックアップの活用
  • Point-in-Time Recovery(PITR)の設定

コーディングのベストプラクティス

  • バッチ操作の活用(BatchGetItem, BatchWriteItem)
  • 条件付き書き込みで楽観的ロックを実装
  • SDKのページネーション機能を活用

まとめ:これだけ覚えておけばOK

DynamoDBの極意
  1. DynamoDBはスケーラビリティとパフォーマンスに優れたNoSQLデータベース
  2. 「どうデータを取り出すか」から設計を始める
  3. パーティションキーの選定がパフォーマンスの鍵
  4. JOINがないので、アクセスパターンに合わせた非正規化が必要
  5. GSIを効果的に活用して複数の検索パターンを実現
  6. コスト管理は、使用パターンに合わせたモード選択と定期的な見直しが重要
これでDynamoDBの基本から実践的な活用方法まで、コンパクトに理解できるようになりました。どんどん実際に使ってみて、経験を積んでいくことをオススメします!