目次
Amazon DynamoDB 完全ガイド 2026
初心者から実務者向けの包括的解説
Amazon DynamoDB は、任意のスケールで一桁ミリ秒の応答時間を実現する フルマネージド・サーバーレス NoSQL データベース です。スキーマレス設計、自動シャーディング、マルチ AZ 耐久性が特徴で、秒間数十万リクエストのワークロードに対応します。本ドキュメントは、DynamoDB の概念・アーキテクチャ・設計パターン・エコシステム・最新動向を体系的に解説する包括的ガイドです。
ドキュメントの目的
本ガイドは以下を対象としています。
- 初心者向け: DynamoDB とは何か、なぜ必要かを学びたい方
- 開発者向け: テーブル設計・キー設計・アクセスパターン定義を実装したい方
- データアーキテクト向け: Single Table Design / Multi-table Design を検討したい方
- SRE / インフラ向け: グローバルテーブル・レプリケーション・ディザスタリカバリを構築したい方
- 意思決定者向け: RDS vs DynamoDB、Cassandra / MongoDB / Cosmos DB との比較・投資判断
2026 年の DynamoDB エコシステム
- DynamoDB v2 API(プレビュー): パフォーマンス向上、新データ型対応
- オンデマンドスループット改善: 更な コスト削減、ウォームアップ時間短縮
- リソースベースポリシー: IAM ロールなしの直接制御
- Zero-ETL: Redshift / OpenSearch との統合、ノーコード同期
- Aurora DSQL 登場(2024-2025): 関連クエリが必要な用途への代替案
- Vector Search(プレビュー): ベクトル埋め込みの直接保存・検索
- PartiQL オプション: SQL ライク構文での簡易クエリ
定義
AWS 公式による定義:
“Amazon DynamoDB is a fully managed, serverless, key-value NoSQL database designed in the cloud for modern web apps.”
特徴:
- フルマネージド: インフラ管理不要、AWS が可用性・耐久性を保証
- サーバーレス: インスタンス管理、スケーリング、バックアップが自動
- ミリ秒レイテンシー: 平均 1-2ms の応答時間
- 無制限スケール: テーブルサイズ・リクエストスループットの上限なし(パーティション数による)
目次
- 概要
- DynamoDB が解決する課題
- 主な特徴
- アーキテクチャ
- キー設計(最重要)
- セカンダリインデックス
- キャパシティモード
- 主要ユースケース
- データモデリング
- DynamoDB Streams と CDC
- グローバルテーブル
- トランザクション
- DAX(DynamoDB Accelerator)
- バックアップと復元
- エクスポートと統合
- 暗号化とセキュリティ
- パフォーマンスチューニング
- コスト最適化
- 他の類似ツールとの比較
- クライアント・エコシステム
- ベストプラクティス
- トラブルシューティング
- 2025-2026 最新動向
- 学習リソース
- 実装例・活用シーン
- 導入ロードマップ
- 実装チェックリスト
- まとめ
- 参考文献
概要
初心者向けメモ: DynamoDB は「データベース」と聞くと RDS(MySQL / PostgreSQL)を想像するかもしれませんが、全く異なります。DynamoDB は キーを指定して高速にデータを取る ことに特化した NoSQL DB です。「複雑な JOIN が必要」「複数テーブルの複合条件クエリ」が必要なら RDS を選びます。「秒間数万リクエスト」「スキーマ変更が頻繁」「グローバル配信」なら DynamoDB を選びます。
DynamoDB は、キーバリュー + ドキュメント DB のハイブリッド型で、以下を実現します:
- 一桁ミリ秒レイテンシー(平均 1-2ms): 世界規模のトラフィックスパイクにも対応
- スキーマレス設計: 属性の動的追加が可能、テーブル構造の柔軟性
- 自動スケーリング: トラフィック増減に自動対応、キャパシティプラニング不要
- マルチ AZ 耐久性: 99.99% の可用性、複数アベイラビリティゾーンへの自動レプリケーション
- グローバルテーブル: マルチリージョン複製で 99.999% SLA
DynamoDB の位置づけ
【図1】AWS データベーススタックにおける DynamoDB の位置:
graph TD
Apps[アプリケーション]
Apps -->|複雑SQL JOIN 必要| RDS[RDS/Aurora<br/>リレーショナル]
Apps -->|JSON ドキュメント| DocDB[DocumentDB<br/>MongoDB互換]
Apps -->|キーバリュー高速| DDB[DynamoDB<br/>NoSQL]
Apps -->|グラフ検索| Neptune[Neptune<br/>グラフDB]
Apps -->|全文検索| OpenSearch[OpenSearch<br/>検索]
RDS -->|複合分析| Redshift[Redshift<br/>DWH]
DDB -->|リアルタイムログ| Loki["Loki / CloudWatch"]
DDB -->|ベクトル検索| Bedrock["Bedrock<br/>生成AI"]
DynamoDB が解決する課題
1. RDS のスケールアウト限界
❌ RDS の問題:
- Read Replica で水平スケール可能だが、Write は PK ノードに集約
- マスターノード故障時のフェイルオーバーは 30-60 秒のダウンタイム発生
- 秒間 10 万リクエスト規模になると、シャーディング実装が複雑化
✅ DynamoDB の解決:
- 自動パーティショニング、秒間 100 万リクエスト対応可能
- Read / Write 分離不要、全リージョンでマルチアクティブ読み書き
- キャパシティ設定のみで、オペレーション管理ゼロ
2. 運用管理コストの削減
❌ 自作 Cassandra / MongoDB の問題:
- クラスタ管理、バージョン更新、パッチ適用が自社責任
- ディスク容量管理、レプリケーション監視
- 障害時の復旧手順が複雑
✅ DynamoDB のメリット:
- AWS が 99.99% 可用性を保証
- 自動バックアップ(PITR 35 日)、自動フェイルオーバー
- CloudTrail / CloudWatch で監視・ロギング自動
3. グローバルサービス対応
❌ シングルリージョン DB の問題:
- 東京リージョンのユーザーは OK だが、NY・シドニーユーザーは遅延大
- マルチリージョンレプリケーション実装が複雑
✅ DynamoDB グローバルテーブルの利点:
- 複数リージョンでの読み書き可能、低レイテンシーローカルアクセス
- リージョン間自動複製、地域障害時の自動フェイルオーバー
- 99.999% SLA(最高レベルの可用性)
4. スキーマ変更の柔軟性
❌ RDS のスキーマ固定性:
- 新しいカラム追加には ALTER TABLE + ロック
- 大規模テーブルでは数時間のダウンタイム発生
✅ DynamoDB のスキーマレス性:
- 新しい属性は任意に追加可能、既存データに影響なし
- 属性追加に伴う速度低下なし
主な特徴
| 特徴 | 説明 |
|---|---|
| 一桁ミリ秒レイテンシー | 平均 1-2ms の応答時間、P99 も 10ms 以下 |
| スキーマレス | テーブル作成後に属性追加可、JSON ネスト可 |
| 自動シャーディング | パーティションキー分散で自動スケール |
| マルチ AZ 耐久性 | 99.9999999999%(12 個の 9)のデータ耐久性 |
| グローバルテーブル | 複数リージョンでの読み書き、99.999% SLA |
| オンデマンドスケーリング | トラフィックに自動対応、キャパシティプラニング不要 |
| TTL 管理 | 期限切れレコードの自動削除 |
| DynamoDB Streams | 変更ログを 24 時間保持、イベント駆動アーキテクチャ対応 |
| Transactions | ACID トランザクション、複数アイテム更新 |
| DAX キャッシュ | マイクロ秒レイテンシー(ミリ秒から 10 倍高速化) |
アーキテクチャ
初心者向けメモ: DynamoDB のアーキテクチャは 4 層に分かれます。
- テーブル層 - ユーザーが作成・管理
- パーティション層 - AWS が自動分散(見えない)
- レプリケーション層 - 複数 AZ / リージョン自動複製
- API 層 - SDK から GetItem / Query / Scan を呼び出し
DynamoDB のデータ構造
【図2】テーブル → パーティション → レプリカの階層構造:
graph TD
Table["テーブル<br/>(ユーザーが見る視点)"]
Table -->|Partition Key<br/>ハッシュ分散| P1["Partition 1<br/>(user_id: a*)<br/>3,000 RCU<br/>1,000 WCU"]
Table -->|Partition Key| P2["Partition 2<br/>(user_id: b*)<br/>3,000 RCU<br/>1,000 WCU"]
Table -->|Partition Key| P3["Partition N<br/>(user_id: z*)<br/>3,000 RCU<br/>1,000 WCU"]
P1 -->|リアルタイム複製| AZ1["AZ1 レプリカ"]
P1 -->|リアルタイム複製| AZ2["AZ2 レプリカ"]
P1 -->|リアルタイム複製| AZ3["AZ3 レプリカ"]
主要概念
| 概念 | 説明 | 制約・上限 |
|---|---|---|
| テーブル | 複数アイテムの集合 | 最大 400 KB/アイテム、無制限テーブルサイズ |
| アイテム | 1 行(レコード)に相当 | 最大 400 KB |
| 属性 | カラムに相当、ネスト可 | 最大深さ 32 |
| Partition Key(PK) | アイテムの一意識別子、ハッシュ値でパーティション決定 | 必須、最大 2 KB |
| Sort Key(SK) | 同一 PK 内のソート順序、複合主キー構成 | 省略可、最大 1 KB |
| Global Secondary Index(GSI) | テーブルとは異なる PK/SK を定義可 | 最大 20 個(増加可能) |
| Local Secondary Index(LSI) | PK は同一、SK のみ変更 | テーブル作成時のみ定義、最大 5 個 |
パーティション設計
DynamoDB は Partition Key のハッシュ値 でデータを複数パーティションに自動分散:
ユーザーID = "user_12345"
↓
hash("user_12345") % num_partitions
↓ 例:Partition 7
↓
Partition 7(3,000 RCU + 1,000 WCU の上限)
各パーティションの上限:
- Read Capacity Unit(RCU):最大 3,000 / 秒
- Write Capacity Unit(WCU):最大 1,000 / 秒
ホットパーティション(特定 PK への集中)を避けるキー設計が重要。
キー設計(最重要)
初心者向けメモ: DynamoDB の性能・コストは 90% キー設計 で決まります。RDS のように「後で JOIN で対応」はできません。設計段階でアクセスパターンを明確にし、それに合わせてキーを決めることが必須です。
主キー戦略
1. シンプルな主キー(PK のみ)
テーブル: Users
├── PK: user_id
├── Attributes: name, email, created_at, ...
用途: ユーザーマスターデータ、シングルアクセス
クエリ例:
GetItem(user_id = "user_123") → 完全一致検索のみ
Scan で name 検索? → NG(テーブル全読み、コスト爆発)
2. 複合主キー(PK + SK)
テーブル: Orders
├── PK: user_id(パーティション分散)
├── SK: order_id(同一ユーザー内でソート)
├── Attributes: amount, status, created_at, ...
用途: 1:N 関係(ユーザー 1 人 → 複数注文)
クエリ例:
GetItem(user_id = "user_123", order_id = "order_456")
→ 完全一致検索
Query(user_id = "user_123")
→ 同一ユーザーの全注文取得
Query(user_id = "user_123", order_id BETWEEN "2024-01" AND "2024-12")
→ ユーザーの特定期間注文のみ取得
アクセスパターン先行設計
ステップ 1:アクセスパターンを列挙
- ユーザー ID で注文を全て取得
- ステータスが「未配送」の注文のみフィルタ
- 注文日時が 2024-01-01 以降の注文
- 注文ステータス(“pending”, “shipped”, “delivered”)で検索
ステップ 2:キー設計検討
❌ アンチパターン:
PK: order_id
SK: status
→ 理由:user_id で検索不可
✅ 推奨:
PK: user_id
SK: created_at (ISO 8601 形式)
GSI1_PK: status
GSI1_SK: created_at
→ 理由:PK で user_id 検索、GSI で status 検索 可能
ホットパーティション回避
❌ アンチパターン 1:ステータスを PK にする
- PK: status (“active”, “inactive” のみ 2 種類)
- → 問題:全トラフィックが 2 パーティションに集約
- → パーティションあたり 3,000 RCU / 1,000 WCU 上限に即座に達する
❌ アンチパターン 2:タイムスタンプ PK
- PK: date (“2026-04-26” など、日単位)
- → 問題:今日のデータに全トラフィック集約
- → 過去のパーティションは遊休状態
✅ 推奨:Write Sharding
PK: order_type + "#" + suffix
例:"order#" + random(0-99)
→ 同じ order_type でも 100 パーティションに分散
→ 秒間 3,000 * 100 = 30 万リクエスト対応可能
キー設計パターン表
| パターン | PK | SK | 向き | 例 |
|---|---|---|---|---|
| Entity | entity_id | - | マスターデータ | user_id |
| 1:N 関係 | parent_id | child_id | ユーザー:注文 | user_id + order_id |
| タイムシリーズ | device_id | timestamp | IoT / ログ | sensor_id + unix_time |
| ステータス管理 | resource_id | status + created_at | 状態遷移 | order_id + (status + timestamp) |
| タグ検索 | tag_name | resource_id | タグベース分類 | “important” + task_id |
| 逆ルックアップ | user_id | メール → ID | GSI 活用 |
セカンダリインデックス
初心者向けメモ: テーブルの主キーでは「あのアクセスパターン」に対応できない → 「セカンダリインデックス」で追加の視点を作ります。RDB の INDEX と異なり、完全に独立したテーブルに近い構造です。
GSI(Global Secondary Index)
テーブル: Orders
├── PK: user_id, SK: order_id
├── GSI1: PK=status, SK=created_at
│ └─ テーブルと別のパーティション、独立キャパシティ
└── Attributes: amount, shipping_address, ...
特徴:
- テーブルから独立: 別キャパシティ設定
- 最大 20 個 (増加リクエスト可)
- 後から追加可能(オンラインで作成、既存テーブル無停止)
- 弱整合性 (レプリケーションラグ数百ミリ秒)
用途例:
# テーブルは user_id で検索、GSI は status で検索
Query(status = "pending") ← GSI 経由
→ "pending" の全注文(user_id 不問)取得
LSI(Local Secondary Index)
テーブル: Orders
├── PK: user_id (同一)
├── SK: order_id
├── LSI1: PK: user_id, SK: amount
│ └─ テーブルと同じパーティション
└── 強整合性クエリ可能
特徴:
- PK は同一、SK のみ変更
- テーブル作成時のみ定義 (後から追加不可)
- 最大 5 個
- テーブルと容量共有
- 強整合性 クエリ可能
用途例:
# ユーザーの注文を金額でソート
Query(user_id = "user_123", amount > 10000) ← LSI 経由、強整合
GSI vs LSI 比較表
| 軸 | GSI | LSI |
|---|---|---|
| PK 変更 | ✅ 可能 | ❌ 不可(同一 PK) |
| SK 変更 | ✅ 可能 | ✅ 可能 |
| キャパシティ | 独立設定 | テーブル共有 |
| 整合性 | 弱整合性 | 強整合性 |
| 作成タイミング | いつでも | テーブル作成時のみ |
| 個数上限 | 20(増加可) | 5 |
| パーティション | テーブル分離 | テーブル同一 |
| 最大アイテムサイズ | 10 GB(パーティション内) | 10 GB |
インデックス設計チェックリスト
✅ アクセスパターンごとに必要なキーを洗い出した ✅ GSI は最大 3-4 個に絞った(キャパシティ管理・コスト削減) ✅ 未使用インデックスは削除した(月 $0.25/GB のストレージ課金) ✅ スパース GSI(一部アイテムのみにキー属性がある)を活用した ✅ GSI SK に使う属性の cardinality は十分か確認した
キャパシティモード
初心者向けメモ: DynamoDB の料金体系は 2 種類。「オンデマンド = 従量課金」「プロビジョンド = 定額 + 予約割引」。本番環境では、アクセスパターンの予測可能性で選択します。スパイク型なら「オンデマンド」、定常なら「プロビジョンド + AutoScaling」が一般的。
オンデマンドモード(On-Demand)
課金 = (読み取り RRU 数) × $0.25/100万 RRU + (書き込み WRU 数) × $1.25/100万 WRU
特徴:
- 従量課金 - 実際の読み書きのみ課金
- 自動スケール - 突然の 100 倍トラフィック増でも対応可能
- 初期キャパシティ不要 - キャパシティプラニングなし
向き:
- ✅ アクセス量が不予測(スパイク型)
- ✅ マイナー機能・テスト環境
- ✅ 新規サービス立ち上げ(トラフィック予測困難)
- ❌ ベースロードが大きい(50 万 RRU/日 以上)
価格イメージ:
- 1 日 50 万リクエスト:$125 / 月(オンデマンド)
- 同じ負荷:プロビジョンド 208 RCU($100/月)→ オンデマンドが高い
プロビジョンドモード(Provisioned)
課金 = 設定 RCU × $0.00013/時間 + 設定 WCU × $0.00065/時間
+ 予約割引(1 年 / 3 年 = 最大 50% 割引)
特徴:
- 定額課金 - 設定容量に対する固定費
- 予測可能な負荷向け - 定常的なトラフィック
- オートスケーリング - Target Utilization に基づき自動調整
向き:
- ✅ ベースロードが大きく定常的(100 万 RRU/日 以上)
- ✅ オンデマンドより 50% 以上安い場合
- ✅ 予約割引で 1 年 / 3 年コミット可能
- ❌ トラフィック予測困難(スパイク)
オートスケーリング設定例:
ターゲット使用率:70%
最小キャパシティ:100 RCU
最大キャパシティ:10,000 RCU
↓
CPU 70% 超過 → キャパシティ自動上昇
CPU 70% 未満 → キャパシティ自動低下(1 分単位)
読み取り / 書き込みキャパシティユニット
RCU(Read Capacity Unit)- 読み取り
| 操作 | アイテムサイズ | 消費 RCU(強整合) | 消費 RCU(弱整合) |
|---|---|---|---|
| GetItem | 4 KB 以下 | 1 | 0.5 |
| GetItem | 4-8 KB | 2 | 1 |
| Query | 4 KB 以下 × 100 件 | 100 | 50 |
| Scan | 4 KB 以下 × 1000 件 | 1000 | 500 |
| TransactGetItem | 4 KB 以下 | 2 | 1 |
WCU(Write Capacity Unit)- 書き込み
| 操作 | アイテムサイズ | 消費 WCU |
|---|---|---|
| PutItem | 1 KB 以下 | 1 |
| PutItem | 1-2 KB | 2 |
| UpdateItem | 1 KB 以下 | 1 |
| DeleteItem | 任意 | 1 |
| TransactWriteItems | 1 KB 以下 | 2 |
| BatchWriteItem | 1 KB 以下 × 25 件 | 25 |
計算例:
User テーブル:1 日 100 万 GetItem(4KB 以下)
→ 100 万 GetItem × 1 RCU = 100 万 RCU
→ 秒あたり:100 万 / 86,400 秒 ≈ 11.6 RCU 必要
モード選択フロー
graph TD
Q1{トラフィック<br/>予測可能?}
Q1 -->|YES| Q2{定常的で<br/>大規模?<br/>100万RRU+}
Q1 -->|NO| OnDemand["オンデマンド<br/>✅ スパイク対応<br/>✅ 自動スケール"]
Q2 -->|YES| Prov["プロビジョンド<br/>✅ 50%安い<br/>✅ 予約割引対象"]
Q2 -->|NO| OnDemand2["オンデマンド<br/>✅ 小規模定常"]
Prov -->|+ AutoScaling| ProvAS["プロビジョンド<br/>+ オートスケーリング<br/>✅ 最適解"]
主要ユースケース
初心者向けメモ: DynamoDB は「監視」「ログ」「キャッシュ」など 10+ のユースケースで活躍。ユースケースに合わせた設計パターンが存在します。
1. セッション・認証データ管理
テーブル: Sessions
├── PK: session_id
├── SK: user_id
├── TTL: expires_at (自動削除)
└── Attributes: jwt_token, ip_address, device_type
特徴:
- ✅ TTL で期限切りセッション自動削除
- ✅ ミリ秒レイテンシーでログイン高速化
- ✅ 秒間数万ユーザー同時アクセス対応
コスト削減: TTL 削除に WCU 不要
2. リアルタイムアナリティクス・カウンター
テーブル: PageViews
├── PK: page_id
├── SK: timestamp
├── Attributes: user_count, session_count
特徴:
- ✅ Atomic Counter(UpdateItem で +1)でアクセス数リアルタイム更新
- ✅ IAM ロール限定で「匿名ユーザーがカウンター +1」を許可
- ✅ DAX キャッシュで PV 閲覧を µs レイテンシー化
実装例:
client.update_item(
TableName='PageViews',
Key={'page_id': 'index.html', 'timestamp': '2026-04-26'},
UpdateExpression='ADD views :inc',
ExpressionAttributeValues={':inc': 1}
)
3. ゲーム - スコア・ランキング・アイテム管理
テーブル: PlayerScores
├── PK: player_id
├── SK: game_session_id
├── GSI: game_id + score (ランキング取得)
└── Attributes: score, level, items_owned, achievements
テーブル: Inventory
├── PK: player_id
├── SK: item_id
└── Attributes: quantity, rarity, equipped
特徴:
- ✅ 秒間数十万プレイヤーの同時スコア更新
- ✅ ランキング(
Query(game_id, score DESC))高速取得 - ✅ アイテム所有数の Atomic Counter 更新
ゲーム業界採用事例:
- AWS Gaming Day(業界カンファレンス)で多数講演
- モバイルゲーム企業の 70% 以上が DynamoDB 採用
4. IoT・時系列データ
テーブル: SensorReadings
├── PK: device_id
├── SK: timestamp (UNIX タイムスタンプ ISOの方が検索効率 ↑)
├── TTL: timestamp + 7 days (自動期限切れ削除)
└── Attributes: temperature, humidity, pressure, location
特徴:
- ✅ Write Sharding で秒間数百万センサー読み込み対応
- ✅ TTL で古いデータ自動削除(ディスク節約)
- ✅ TimeToLive 機能でストレージコスト自動削減
IoT 企業採用事例:
- AWS IoT Core との統合
- AWS Greengrass 連携
5. E コマース - ショッピングカート・注文管理
テーブル: Carts
├── PK: user_id
├── SK: cart_session_id
├── TTL: session_expires_at
└── Attributes: items: [{product_id, quantity, price}], subtotal
テーブル: Orders
├── PK: order_id
├── SK: timestamp
├── GSI: user_id + timestamp (ユーザーの注文履歴)
└── Attributes: items, shipping_address, payment_status
特徴:
- ✅ ショッピングカートはセッション永続化
- ✅ ブラウザ購入継続時の復帰高速化
- ✅ 注文データは GSI で「ユーザーの全注文」クエリ
6. リアルタイムメッセージング・チャット
テーブル: Messages
├── PK: conversation_id
├── SK: timestamp
├── GSI: user_id + timestamp (ユーザーの全会話)
└── Attributes: sender_id, content, media_urls
特徴:
- ✅ 会話 ID でメッセージ時系列取得
- ✅ DynamoDB Streams で WebSocket / Pub-Sub トリガー
- ✅ DAX で頻繁にアクセスされる会話をキャッシュ
7. メタデータ・コンテンツ管理
テーブル: Content
├── PK: content_id
├── SK: version
├── Attributes: title, author, metadata (nested JSON), tags
特徴:
- ✅ スキーマレスで属性動的追加
- ✅ ネストされた JSON (List / Map)を直接保存
- ✅ 複数バージョン管理(SK = version)
8. 推奨システム・人気度ランキング
テーブル: PopularityScores
├── PK: category
├── SK: popularity_score DESC
├── GSI: updated_at + category (最新更新順)
└── Attributes: product_id, views, likes, revenue
特徴:
- ✅ Query で上位 N 件高速取得
- ✅ UpdateItem で人気度リアルタイム更新
9. コンプライアンス・監査ログ
テーブル: AuditLog
├── PK: resource_type
├── SK: timestamp
├── Attributes: action, actor_id, target_id, changes, ip_address
特徴:
- ✅ 改ざん防止:DynamoDB Streams で外部システムへリアルタイムレプリケーション
- ✅ CloudTrail 連携で管理操作も記録
- ✅ S3 Export で長期保管
10. SaaS マルチテナント
テーブル: Workspaces
├── PK: tenant_id
├── SK: resource_id
├── Attributes: org_name, members, settings, subscription_tier
テーブル: Invitations
├── PK: tenant_id
├── SK: invitation_code
├── TTL: expires_at
└── Attributes: invitee_email, role
特徴:
- ✅ 各テナントデータを PK で完全分離
- ✅ 招待コードは TTL で自動期限切れ
- ✅ tenant_id がパーティションキー → テナント数に自動スケール
ユースケース適性マトリクス
| ユースケース | 適性 | 料金目安(月) | 備考 |
|---|---|---|---|
| セッション管理 | ★★★★★ | $50-200 | TTL で自動削除 |
| リアルタイム PV | ★★★★★ | $100-500 | Atomic Counter |
| ゲームランキング | ★★★★★ | $200-1000 | GSI ランキング |
| IoT タイムシリーズ | ★★★★★ | $500-2000 | Write Sharding 必須 |
| E コマース | ★★★★ | $300-1500 | 注文・カート分離 |
| リアルタイムチャット | ★★★★ | $100-1000 | Streams 連携 |
| メタデータ管理 | ★★★★ | $50-500 | スキーマレス活用 |
| 推奨エンジン | ★★★★ | $200-800 | Streams → ML Pipeline |
| 監査ログ | ★★★ | $100-500 | S3 Export 併用 |
| SaaS マルチテナント | ★★★★ | $500-3000 | テナントスケーリング |
データモデリング
初心者向けメモ: DynamoDB のデータモデリングは RDB と大きく異なります。RDB では「正規化」を重視し、データ冗長を排除します。DynamoDB では「非正規化」を重視し、アクセスパターンに合わせてデータを複製・集約します。これを Single Table Design と呼びます。
Single Table Design(推奨)
複数エンティティを 1 つのテーブルに統合:
テーブル: Orders
├── 行 1: PK=order#123, SK=order_metadata
│ └─ Attributes: status, created_at, total_amount
├── 行 2: PK=order#123, SK=customer#user_456
│ └─ Attributes: name, email, address
├── 行 3: PK=order#123, SK=item#product_789
│ └─ Attributes: quantity, price, sku
└── 行 4: PK=order#123, SK=shipment#tracking_001
└─ Attributes: carrier, tracking_number, estimated_delivery
メリット:
- ✅ 1 回の Query で注文 + 顧客 + アイテム + 配送情報を全取得
- ✅ トランザクション(TransactWriteItems)で一括更新
- ✅ JOIN 不要で高速(HTTP ラウンドトリップ 1 回)
- ✅ ソート順序で関連データを自動グループ化
デメリット:
- ❌ テーブル設計が複雑(アクセスパターン要綿密分析)
- ❌ データ冗長増加(アイテム数増加 → ストレージ増加)
- ❌ 複雑なテーブルスキャン不可(Scan は避ける)
Multi-Table Design(代替)
複数テーブルに分散:
テーブル: Orders
├── PK: order_id
├── Attributes: status, created_at, total_amount
テーブル: Customers
├── PK: customer_id
├── Attributes: name, email, address
テーブル: OrderItems
├── PK: order_id
├── SK: item_index
├── Attributes: product_id, quantity, price
メリット:
- ✅ テーブル設計がシンプル
- ✅ 学習曲線が緩い
- ✅ 複数テーブルスキャン可能
デメリット:
- ❌ HTTP ラウンドトリップ複数回(遅い)
- ❌ 複数テーブル更新時のトランザクション複雑化
- ❌ JOIN ロジックをアプリケーション側で実装
比較表
| 軸 | Single Table Design | Multi-Table Design |
|---|---|---|
| アクセス速度 | 高速(1 Query) | やや低速(複数 Query) |
| 設計の複雑性 | 高い | 低い |
| ストレージ効率 | 低い(冗長) | 高い(正規化) |
| トランザクション | 簡単 | 複雑 |
| 学習コスト | 高い | 低い |
| 推奨対象 | 大規模・高トラフィック | 小規模・学習目的 |
スキーマ設計ベストプラクティス
# ❌ アンチパターン:深いネスト
item = {
'order_id': '123',
'customer': {
'personal': {
'contact': {
'email': 'user@example.com' # 深すぎる
}
}
}
}
# ✅ 推奨:フラットな属性
item = {
'order_id': '123',
'customer_email': 'user@example.com',
'customer_name': 'John Doe'
}
# ✅ または:Map(JSON)活用
item = {
'order_id': '123',
'customer': {
'email': 'user@example.com',
'name': 'John Doe'
}
}
DynamoDB Streams と CDC
初心者向けメモ: DynamoDB Streams は「テーブルへの全変更(Insert / Update / Delete)をログとして記録」する機能です。これを Lambda / Kinesis に繋げば、変更に応じたアクションを自動実行できます。これが イベント駆動アーキテクチャ の基盤です。
DynamoDB Streams の仕組み
テーブルへの書き込み
↓
DynamoDB Streams(変更ログ、24 時間保持)
├─→ AWS Lambda (トリガー)→ 検索インデックス更新 / 通知送信
├─→ Kinesis Data Streams (長期保持・分析)
├─→ AWS Glue (ETL パイプライン)
└─→ 他リージョンのテーブル (グローバルテーブル複製に内部利用)
ストリームビュータイプ
| ビュータイプ | 説明 | 用途 |
|---|---|---|
| KEYS_ONLY | 変更されたアイテムキーのみ | 変更通知のみ必要 |
| NEW_IMAGE | 新しい値のみ | 新規アイテムをキャッシュに追加 |
| OLD_IMAGE | 旧値のみ | 変更前後の差分監視 |
| NEW_AND_OLD_IMAGES | 新旧両方 | 変更内容を完全把握(最重い) |
Lambda トリガーの実装例
# DynamoDB → Lambda トリガー
def lambda_handler(event, context):
for record in event['Records']:
if record['eventName'] == 'INSERT':
# 新規アイテムを OpenSearch にインデックス化
item = record['dynamodb']['NewImage']
index_in_opensearch(item)
elif record['eventName'] == 'MODIFY':
# 変更後の値を Redshift に同期
new_item = record['dynamodb']['NewImage']
sync_to_redshift(new_item)
elif record['eventName'] == 'REMOVE':
# 削除されたアイテムをキャッシュから削除
key = record['dynamodb']['Keys']
remove_from_cache(key)
CDC(Change Data Capture)パターン
graph LR
DDB["DynamoDB テーブル"]
Stream["DynamoDB Streams"]
Lambda["Lambda Function"]
subgraph "下流システム"
ES["OpenSearch<br/>(全文検索)"]
Redis["Redis<br/>(キャッシュ)"]
RDS["RDS<br/>(分析用複製)"]
end
DDB -->|変更ログ| Stream
Stream -->|イベント| Lambda
Lambda -->|インデックス更新| ES
Lambda -->|キャッシュ更新| Redis
Lambda -->|同期書き込み| RDS
グローバルテーブル
初心者向けメモ: DynamoDB グローバルテーブルは「複数リージョンで同じテーブルをマルチアクティブ複製」する機能です。東京のユーザーは東京リージョンのテーブルに、NY のユーザーは us-east-1 テーブルに読み書き → 自動複製で最終一貫性を保証。
グローバルテーブルの仕組み
リージョン A(ap-northeast-1)
┌─────────────────────┐
│ テーブル Order │◄──────────┐
│ (Read/Write) │ │
└─────────────────────┘ │
│ ▲ 変更ログ複製
│ │ DynamoDB Streams (非同期、100-200ms)
│ │ │
│ └────────────────────┼──────────┐
│ │ │
リージョン B(us-east-1) │ リージョン C(eu-west-1)
┌─────────────────────┐ │ ┌──────────────────┐
│ テーブル Order │ └─►│ テーブル Order │
│ (Read/Write) │ │ (Read/Write) │
└─────────────────────┘ └──────────────────┘
特徴:
- ✅ すべてのリージョンで読み書き可能(マルチアクティブ)
- ✅ 可用性 SLA:99.999%(5 つの 9)
- ✅ 複製遅延:通常 100-200ms(最終一貫性)
- ✅ TTL・GSI も自動複製
競合解決戦略
複数リージョンで同時に同じアイテムを更新した場合:
東京リージョン:order_id#123 update → status = "shipped"
↑ ↑
└─────────────────────────────────────────┘
200ms
↑ ↑
米国リージョン:order_id#123 update → status = "delivered"
デフォルト:Last Writer Wins(LWW)
- タイムスタンプが新しい方が勝つ
- アプリケーション論理が強く統制できる場合に有効
グローバルテーブルの構成
# Terraform で構成
resource "aws_dynamodb_table" "orders_global" {
name = "orders"
hash_key = "order_id"
# グローバルテーブル有効化
stream_specification {
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
}
replica {
region_name = "us-east-1"
}
replica {
region_name = "eu-west-1"
}
}
グローバル vs シングルリージョン比較
| 軸 | グローバルテーブル | シングルリージョン |
|---|---|---|
| 可用性 SLA | 99.999% | 99.99% |
| 読み取りレイテンシー | ローカル 1-2ms | リモート 50-100ms |
| 複製遅延 | 100-200ms | N/A |
| 構成複雑性 | 高い | 低い |
| 月額コスト | 複製ストレージ分増加 | 基本料金のみ |
| **向き | グローバルサービス | 単一リージョン |
トランザクション
初心者向けメモ: DynamoDB トランザクションは「複数アイテムの原子性更新」を実現します。全て成功 or 全て失敗(All-or-Nothing)。銀行口座振替(A から B への送金)など、一貫性が必須の処理に有効です。
TransactWriteItems(書き込みトランザクション)
import boto3
dynamodb = boto3.client('dynamodb')
response = dynamodb.transact_write_items(
TransactItems=[
{
'Put': {
'TableName': 'Accounts',
'Item': {
'account_id': {'S': 'savings_123'},
'balance': {'N': '900'} # 100 減少
},
'ConditionExpression': 'attribute_exists(account_id)'
}
},
{
'Put': {
'TableName': 'Accounts',
'Item': {
'account_id': {'S': 'checking_456'},
'balance': {'N': '1100'} # 100 増加
},
'ConditionExpression': 'attribute_exists(account_id)'
}
}
]
)
特徴:
- ✅ Put / Update / Delete / ConditionCheck を組み合わせ可
- ✅ 最大 100 アイテムまたは 4 MB の制限
- ✅ 同一リージョン内のみ(グローバルテーブル間不可)
- ✅ WCU を 2 倍消費(通常 1 WCU = 1 KB,トランザクション = 2 WCU)
TransactGetItems(読み取りトランザクション)
response = dynamodb.transact_get_items(
TransactItems=[
{
'Get': {
'TableName': 'Accounts',
'Key': {'account_id': {'S': 'savings_123'}}
}
},
{
'Get': {
'TableName': 'Accounts',
'Key': {'account_id': {'S': 'checking_456'}}
}
}
]
)
# 両方のアカウントが一貫した状態で読み込まれることを保証
accounts = response['Responses']
特徴:
- ✅ 複数アイテムの一貫性読み込み
- ✅ RCU を 2 倍消費(強整合)
条件付き更新(ConditionCheck)
# トランザクション内で条件を検証
{
'Update': {
'TableName': 'Orders',
'Key': {'order_id': {'S': 'order_123'}},
'UpdateExpression': 'SET #status = :new_status',
'ConditionExpression': '#status = :old_status', # 現在のステータス確認
'ExpressionAttributeNames': {'#status': 'status'},
'ExpressionAttributeValues': {
':new_status': {'S': 'shipped'},
':old_status': {'S': 'pending'}
}
}
}
DAX(DynamoDB Accelerator)
初心者向けメモ: DynamoDB のレイテンシーはすでに 1-2ms と高速ですが、「マイクロ秒」レベルが必要な場合(ゲーム内高頻度読み取り、リアルタイムビッド)は DAX を使います。インメモリキャッシュで 10 倍高速化します。
DAX の動作
アプリケーション
│
│ キャッシュあり?
▼
[DAX クラスター]
├─ ヒット:µs 単位で返却
└─ ミス:DynamoDB へ問い合わせ → キャッシュに保存
│
▼
DynamoDB テーブル
特徴:
- ✅ レイテンシー:ミリ秒 → マイクロ秒(10-100 倍高速化)
- ✅ 読み取りキャッシュ(デフォルト)
- ✅ Write-through キャッシュ(書き込みも DAX 経由)
- ✅ TTL で期限切りエントリ自動削除
- ✅ VPC 内デプロイ(パブリックアクセス不可)
DAX クラスター構成
最小構成:1 ノード(テスト)
推奨構成:3 ノード(マルチ AZ)
最大構成:11 ノード(高可用性)
ノードサイズ:
├─ dax.r4.large (26 GB、$0.316/時間)
├─ dax.r4.xlarge (52 GB、$0.632/時間)
└─ dax.r4.2xlarge (104 GB、$1.265/時間)
月額コスト試算
DAX 3 ノード(dax.r4.large):
= $0.316/時間 × 3 ノード × 730 時間(月)
≈ $692 / 月
DynamoDB 読み取り削減効果:
キャッシュヒット率 90% の場合、RCU 90% 削減
1,000 RCU × $0.00013/時間 × 730 時間 × 90% = $85 / 月削減
結論:DAX コスト > 削減額 → ハイトラフィック用途でのみ採算
DAX を使うべき用途
✅ ゲーム内ランキング(読み取り集中) ✅ リアルタイムビッディング ✅ 広告配信ターゲティング(頻繁な参照) ✅ キャッシュミス後の MISS 処理が遅い場合
❌ 書き込み主体のワークロード ❌ データ鮮度が重要(リアルタイム要求) ❌ キャッシュ一貫性が複雑
バックアップと復元
初心者向けメモ: DynamoDB はマネージドサービスなので自動バックアップが有効。PITR(Point-in-Time Recovery)で過去 35 日間の任意の時点に復元可能。削除したデータ復旧も簡単。
PITR(Point-in-Time Recovery)
特徴:
- ✅ 自動有効化(デフォルト ON)
- ✅ 35 日間の履歴保持
- ✅ 秒単位で復元時点指定可
- ✅ 新規テーブルとして復元(既存テーブル上書きなし)
用途:
- 誤削除データの復旧
- ランサムウェア対策(一定期間前の状態に戻す)
- テーブルスキーマリセット
復元例:
# AWS CLI で 24 時間前に復元
aws dynamodb restore-table-to-point-in-time \
--source-table-name Orders \
--target-table-name Orders-restored \
--restore-date-time 2026-04-25T10:00:00Z
オンデマンドバックアップ
特徴:
- ✅ 手動作成・スケジューリング
- ✅ テーブル容量に関係なく瞬時完了
- ✅ 無期限保持(削除まで)
- ✅ 月あたり 1 テーブル 1 個は無料
用途:
- 大型リリース前の事前バックアップ
- 外部コンプライアンス要件対応(監査証跡)
- 長期アーカイブ
バックアップストレージ料金
PITR:無料(テーブルストレージと同額)
オンデマンドバックアップ:$0.10/GB/月
例)500 GB テーブルの 7 世代バックアップ保持:
= 500 GB × 7 × $0.10 = $350 / 月
エクスポートと統合
初心者向けメモ: DynamoDB のデータを S3 にエクスポート → Athena / Redshift / OpenSearch で分析。これが「Zero-ETL」フロー。Lambda / Glue 不要で完全にノーコード。
S3 エクスポート
DynamoDB テーブル
│
▼(ParquetまたはJSON形式)
S3 バケット(テーブル内容をスナップショット)
│
├─→ Athena(SQL クエリ)
├─→ Redshift(DWH に一括ロード)
├─→ OpenSearch(フルテキスト検索)
├─→ QuickSight(BI ダッシュボード)
└─→ SageMaker(機械学習)
特徴:
- ✅ テーブル無停止でエクスポート
- ✅ Parquet 形式で高圧縮(ストレージ 80% 削減)
- ✅ 指定時点のスナップショット(PITR と連携可)
Athena で即座に分析:
-- S3 内の Parquet ファイルに SQL クエリ
SELECT user_id, COUNT(*) as order_count
FROM s3://my-bucket/exports/orders/
WHERE created_at > '2026-04-01'
GROUP BY user_id
ORDER BY order_count DESC;
Redshift Zero-ETL
# DynamoDB → Redshift(完全自動複製)
aws dynamodb create-replica(
TableName: Orders,
ReplicaArn: arn:aws:redshift:...
)
→ リアルタイムで Redshift に複製
複雑な JOIN / 集計可能
OpenSearch Zero-ETL
DynamoDB テーブル
│ Streams トリガー
▼
Lambda Function
│(インデックスリクエスト)
▼
OpenSearch ドメイン
│(全文検索インデックス)
▼
Kibana ダッシュボード
暗号化とセキュリティ
初心者向けメモ: DynamoDB は保存時・転送時・アクセス制御の 3 層でセキュリティを確保。デフォルトでも AWS 所有キー(AES256)で暗号化されていますが、本番環境では KMS カスタマーマネージドキーを使用。
保存時暗号化(Encryption at Rest)
| キー管理方式 | 説明 | コスト |
|---|---|---|
| AWS 所有キー | AWS が完全管理、デフォルト | 無料 |
| AWS マネージドキー | テーブルごとに自動キー作成 | 無料 |
| カスタマーマネージドキー(KMS) | 顧客が作成・管理、監査ログ有 | $1/月 + API 呼び出し |
推奨:KMS カスタマーマネージドキー
# KMS キー作成
aws kms create-key --description "DynamoDB encryption key"
# DynamoDB テーブルで KMS キー指定
aws dynamodb create-table \
--table-name Orders \
--key-schema AttributeName=order_id,KeyType=HASH \
--sse-specification Enabled=true,SSEType=KMS,KMSMasterKeyId=arn:aws:kms:...
転送時暗号化(Encryption in Transit)
- ✅ HTTPS/TLS 1.2 以上は必須
- ✅ VPC Endpoint 経由でプライベートアクセス(InternetGateway 不要)
VPC Endpoint 構成例:
アプリケーション(EC2 / Lambda)
│(プライベート)
▼
[VPC Endpoint]
│(AWS 内部ネットワーク)
▼
DynamoDB
IAM アクセス制御
細粒度権限:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query"
],
"Resource": "arn:aws:dynamodb:ap-northeast-1:123456789:table/Orders",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-1234567890"
}
}
}
]
}
操作単位の制御:
dynamodb:GetItem- 単一アイテム読み取りdynamodb:Query- 範囲検索dynamodb:Scan- テーブル全読み(制限推奨)dynamodb:PutItem- 書き込みdynamodb:UpdateItem- 更新dynamodb:DeleteItem- 削除
リソースベースポリシー(2024-2025 新機能)
IAM ロール不要でテーブルへの直接制御:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789:role/AppRole"
},
"Action": "dynamodb:GetItem",
"Resource": "arn:aws:dynamodb:ap-northeast-1:123456789:table/Orders"
}
]
}
パフォーマンスチューニング
ホットパーティション対策
❌ 問題パターン:
- PK: status (“active” のみ)
- → 全リクエストが 1 パーティションに集約
- → 3,000 RCU / 1,000 WCU 上限に即座に抵触
✅ Write Sharding 対策:
# PK にランダムサフィックスを追加
import random
user_id = "user_123"
shard_id = random.randint(0, 99)
pk = f"{user_id}#{shard_id:02d}"
# → user_123#00, user_123#01, ... user_123#99
# → 100 パーティションに分散 → 秒間 100 万リクエスト対応可能
Adaptive Capacity
DynamoDB が自動的にホットパーティションに一時的に追加容量を割り当て(最大 4 時間)。
- ✅ プロビジョンドモード + AutoScaling の場合のみ有効
- ✅ スケーリング時間を稼ぐ緊急対策(根本解決ではない)
Scan vs Query
| 操作 | 用途 | コスト効率 |
|---|---|---|
| GetItem | PK + SK で単一アイテム取得 | 最安 |
| Query | PK で複数アイテム取得(SK 範囲指定可) | 中 |
| Scan | テーブル全体読み取り | 高(避けるべき) |
Scan 回避パターン:
# ❌ 悪い例
response = dynamodb.scan(
TableName='Orders',
FilterExpression='#status = :status',
ExpressionAttributeNames={'#status': 'status'},
ExpressionAttributeValues={':status': 'pending'}
)
# ✅ 良い例:GSI で Query に変更
response = dynamodb.query(
TableName='Orders',
IndexName='status-created_at-index',
KeyConditionExpression='#status = :status',
ExpressionAttributeNames={'#status': 'status'},
ExpressionAttributeValues={':status': 'pending'}
)
バッチ操作
# ネットワークラウンドトリップ削減
response = dynamodb.batch_get_item(
RequestItems={
'Orders': {
'Keys': [
{'order_id': {'S': 'order_1'}},
{'order_id': {'S': 'order_2'}},
# ... 最大 100 件
]
}
}
)
コスト最適化
初心者向けメモ: DynamoDB のコストは「読み取り」「書き込み」「ストレージ」「通信」の 4 要素で構成。各要素を最適化するチェックリストを整備。
コスト構成
月額 DynamoDB 料金
├─ 読み取り容量料金(RCU):30-40%
├─ 書き込み容量料金(WCU):30-40%
├─ ストレージ料金:5-10%
├─ データ転送料金:5-10%
└─ その他(Streams / Backups):5-10%
最適化施策
1. キャパシティモード最適化
| 施策 | 削減率 |
|---|---|
| オンデマンド → プロビジョンド(安定負荷) | -40-70% |
| プロビジョンド + 予約割引(1 年) | -30-40% |
| プロビジョンド + 予約割引(3 年) | -50-60% |
2. TTL 活用
- TTL で期限切れレコード自動削除
- → 削除に WCU 不要、ストレージ自動削減
- → 月 $500 削減(例:セッションデータ 100GB)
3. テーブルクラス最適化
| クラス | ストレージ料金 | 読み書き料金 | 向き |
|---|---|---|---|
| Standard | $0.25/GB | 標準料金 | ホットデータ |
| Standard-IA | $0.10/GB(60% 削減) | 1.25 倍 | コールドデータ(アクセス低頻度) |
4. GSI 最適化
未使用 GSI は月 $0.25/GB のストレージ課金
→ 不要 GSI は即座削除
例:500GB テーブル × 3 未使用 GSI
= 500GB × 3 × $0.25 = $375 / 月 削減可能
5. 圧縮・属性削減
# ❌ 冗長なデータ保存
item = {
'order_id': '123',
'user_full_name': 'John Michael Smith', # 25 バイト
'user_email': 'john.michael.smith@example.com', # 35 バイト
'long_description': '...' * 10000 # 大容量テキスト
}
# ✅ 最適化
item = {
'order_id': '123',
'user_id': '456', # ID 参照に変更
# 説明文は S3 に保存、URL のみ参照
'description_url': 's3://bucket/orders/123/desc.txt'
}
月額削減シミュレーション
現在の構成:
├─ オンデマンドモード(100 万 RRU / 日)
├─ RCU 料金:$0.25/100 万 = $75 / 日 = $2,250 / 月
├─ GSI 3 個(各 500 GB ストレージ):$375 / 月
└─ 合計:$2,625 / 月
最適化後:
├─ プロビジョンド 400 RCU(1 年予約):$36 / 月
├─ GSI を 1 個に削減:$125 / 月
├─ TTL で古いデータ削除 → ストレージ 60% 削減
└─ 合計:$200 / 月
削減額:$2,625 - $200 = $2,425 / 月(92% 削減!)
他の類似ツールとの比較
初心者向けメモ: NoSQL DB は多種多様。DynamoDB との違いを理解して選択基準を明確にします。
主要 NoSQL DB 比較表
| 項目 | DynamoDB | Cassandra | MongoDB | Cosmos DB | Firestore | Aurora DSQL(新) |
|---|---|---|---|---|---|---|
| 管理形式 | マネージド | セルフホスト | マネージド | マネージド | マネージド | マネージド |
| レイテンシー | 1-2ms | 5-10ms | 5-20ms | 10-20ms | 5-100ms | 1-5ms(関連クエリ) |
| スケール | 無制限(パーティション分散) | 無制限(クラスタリング) | 制限あり | 無制限 | 制限あり | 無制限 |
| JOIN | ❌ 不可 | ❌ 不可 | ⚠️ 限定的 | ⚠️ 限定的 | ❌ 不可 | ✅ 可能 |
| ACID トランザクション | ✅ 複数アイテム | ❌ | ✅ | ✅ | ✅ | ✅ |
| スキーマレス | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️(スキーマ型も) |
| グローバル分散 | ✅ マルチリージョン | ✅ マルチノード | ⚠️ | ✅ | ✅ | ⚠️(開発中) |
| 運用負荷 | 最小 | 高い | 低い | 低い | 最小 | 低い |
| コスト(初期) | 低 | 中 | 低 | 高 | 低 | 中 |
| 学習曲線 | 急(設計困難) | 中 | 緩い | 緩い | 緩い | 中 |
選択フロー
graph TD
Q1{複雑な<br/>JOIN 必要?}
Q1 -->|YES| Aurora["Aurora(RDS)<br/>✅ ACID<br/>✅ JOIN"]
Q1 -->|NO| Q2{スケール<br/>100万req/s?}
Q2 -->|YES| Q3{運用<br/>自社担当可?}
Q2 -->|NO| MongoDB["MongoDB<br/>✅ スキーマレス<br/>✅ 小規模"]
Q3 -->|YES| Cassandra["Cassandra<br/>✅ 大規模<br/>❌ 運用負荷高"]
Q3 -->|NO| DynamoDB["DynamoDB<br/>✅ マネージド<br/>✅ スケール"]
Q1 -->|MAYBE| DSQL["Aurora DSQL<br/>✅ 関連クエリ<br/>✅ 新型DB"]
クライアント・エコシステム
AWS SDK
| 言語 | SDK 名 | 評価 |
|---|---|---|
| Python | Boto3 | ★★★★★(最も利用) |
| JavaScript/Node.js | AWS SDK for JS | ★★★★★ |
| Java | AWS SDK for Java | ★★★★★ |
| Go | AWS SDK for Go | ★★★★ |
| C#/.NET | AWS SDK for .NET | ★★★★ |
ORM・ドライバ
| ツール | 用途 | 評価 |
|---|---|---|
| DynamoDB DocumentClient | 高レベル API | ★★★★ |
| PynamoDB | Python ORM | ★★★★ |
| dynamoose | Node.js ORM | ★★★ |
| PartiQL | SQL ライク構文 | ★★★(標準化進行中) |
開発補助ツール
| ツール | 用途 | 特徴 |
|---|---|---|
| NoSQL Workbench | GUI 設計・テスト | テーブル設計可視化 |
| DynamoDB Local | ローカル開発 | Docker コンテナ |
| AWS SAM | IaC / デプロイ | CloudFormation 上位互換 |
| Terraform | インフラストラクチャコード | マルチクラウド対応 |
| Serverless Framework | Lambda + DynamoDB | IaC + デプロイ統合 |
ベストプラクティス
テーブル設計
✅ 設計チェックリスト
- [ ] アクセスパターンを 3 つ以上洗い出した
- [ ] ホットパーティション対策を実装した(キー cardinality 検証)
- [ ] GSI は最大 3-4 個に絞った
- [ ] TTL で古いデータ自動削除を設定
- [ ] ネストは 2 層以下に抑えた
- [ ] 400 KB アイテムサイズ上限を考慮
パフォーマンス
✅ パフォーマンスチェックリスト
- [ ] Scan は使わない(Query + GSI に変更)
- [ ] バッチ操作で HTTP ラウンドトリップを削減
- [ ] DAX キャッシュで読み取り集約化(必要な場合)
- [ ] CloudWatch メトリクスで ConsumedCapacity 監視
- [ ] アダプティブキャパシティでホットパーティションを検出
セキュリティ
✅ セキュリティチェックリスト
- [ ] KMS カスタマーマネージドキーで暗号化
- [ ] VPC Endpoint でプライベートアクセス
- [ ] IAM ロールで最小権限設定
- [ ] CloudTrail で API 呼び出しログ
- [ ] ポイントインタイムリカバリ有効化
コスト最適化
✅ コスト最適化チェックリスト
- [ ] 定常負荷はプロビジョンドモード + 予約割引検討
- [ ] オンデマンドはスパイクワークロードのみ
- [ ] TTL で不要データ自動削除
- [ ] 未使用 GSI は削除
- [ ] Standard-IA でコールドデータ移行(月 1 回以下アクセス)
- [ ] AWS Cost Explorer で月間費用を監視
トラブルシューティング
| 症状 | 原因 | 解決策 |
|---|---|---|
| スロットリングエラー(Throttling) | 容量超過 | キャパシティ増加、キー分散化、Write Sharding |
| 遅いQuery | インデックス未使用 | Explain + Query Plan で索引選択を確認、GSI 追加 |
| 高額請求 | 想定外のキャパシティ使用 | CloudWatch Metrics で消費量監視、Scan 回避 |
| トランザクション失敗 | 条件不一致 | ConditionExpression ログ出力、条件式見直し |
| 古いデータ読み取り | 弱整合性読み取り | ConsistentRead=true に変更(RCU 2 倍消費) |
2025-2026 最新動向
1. DynamoDB v2 API(プレビュー)
改善点:
- パフォーマンス向上(特に大規模スキャン)
- 新データ型対応(JSON / Decimal 精度向上)
- ステートフルアプリケーション対応
2. Vector Search(プレビュー)
ベクトル埋め込みを直接保存・検索可能:
# 生成 AI 統合
item = {
'product_id': '123',
'description': 'Ultra-lightweight running shoes',
'embedding': [0.1, 0.2, 0.3, ...] # 1536 次元
}
# 類似商品検索
results = dynamodb.search_by_vector(
embedding=query_embedding,
top_k=10
)
用途:
- 推奨エンジン(Bedrock + Embedding)
- 意味検索(Semantic Search)
3. Aurora DSQL 登場(2024-2025)
DynamoDB に JOIN 機能を追加したような新 DB:
選択基準:
├─ JSON + スケール → DynamoDB
├─ JSON + JOIN が必要 → Aurora DSQL(新)
└─ リレーショナル + スケール → Aurora PostgreSQL + read replicas
4. リソースベースポリシー
IAM ロール不要で直接テーブル制御(セキュリティ向上)
5. Zero-ETL Redshift / OpenSearch
DynamoDB → Redshift / OpenSearch へのノーコード同期
学習リソース
公式ドキュメント
オンラインコース
- AWS Skill Builder:DynamoDB Deep Dive
- Linux Academy:DynamoDB for Developers
- Udemy:DynamoDB Complete Guide
設計パターン
- DynamoDB Design Patterns
- Single Table Design(AWS公式ブログ多数)
- AWS Well-Architected Review
コミュニティ
- AWS Forums(DynamoDB タグ)
- AWS re:Post
- Stack Overflow([amazon-dynamodb] タグ)
実装例・活用シーン
例 1:ユーザー認証・セッション管理
import boto3
from datetime import datetime, timedelta
import json
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Sessions')
def create_session(user_id, jwt_token):
expires_at = int((datetime.now() + timedelta(hours=24)).timestamp())
table.put_item(
Item={
'session_id': f"sess_{user_id}_{int(datetime.now().timestamp())}",
'user_id': user_id,
'jwt_token': jwt_token,
'created_at': int(datetime.now().timestamp()),
'expires_at': expires_at # TTL で自動削除
}
)
def validate_session(session_id):
response = table.get_item(Key={'session_id': session_id})
if 'Item' in response:
return response['Item']['user_id']
return None
例 2:ゲームランキング
def update_player_score(player_id, game_id, score):
# Global Secondary Index を使用
table.update_item(
Key={'player_id': player_id, 'game_id': game_id},
UpdateExpression='SET #score = :score, updated_at = :now',
ExpressionAttributeNames={'#score': 'score'},
ExpressionAttributeValues={
':score': score,
':now': int(datetime.now().timestamp())
}
)
def get_top_players(game_id, limit=10):
# GSI で game_id + score でクエリ
response = table.query(
IndexName='game_id-score-index',
KeyConditionExpression='game_id = :game_id',
ExpressionAttributeValues={':game_id': game_id},
ScanIndexForward=False, # 降順(スコア高い順)
Limit=limit
)
return response['Items']
導入ロードマップ
フェーズ 1:学習・設計(2 週間)
Day 1-3:DynamoDB 概念理解
├─ テーブル、パーティション、インデックス
├─ アクセスパターン分析
└─ キー設計ワークショップ
Day 4-7:プロトタイプ実装
├─ DynamoDB Local で開発環境構築
├─ 簡単なテーブル作成・CRUD
└─ パフォーマンステスト
Day 8-14:設計レビュー・本設計
├─ AWS Well-Architected Review
├─ セキュリティ・コスト最適化検討
└─ 本番環境設計書作成
フェーズ 2:開発・テスト(4 週間)
Week 1-2:コア機能実装
├─ SDK 統合
├─ エラーハンドリング
└─ 単体テスト
Week 3:統合テスト・パフォーマンステスト
├─ 大規模データロード
├─ 負荷テスト(k6)
└─ レイテンシー・スループット検証
Week 4:本番環境準備
├─ CloudFormation / Terraform 自動化
├─ バックアップ・復旧テスト
└─ 運用手順書作成
フェーズ 3:本番稼働・最適化(継続)
Week 1:カナリア導入(5% トラフィック)
Week 2:段階的拡大(25%)
Week 3:50% 移行
Week 4:100% 移行完了
その後:
├─ CloudWatch 監視
├─ コスト最適化(月 1 回)
├─ キャパシティプランニング(四半期 1 回)
└─ セキュリティレビュー(半年 1 回)
実装チェックリスト
設計フェーズ
- [ ] アクセスパターンを最低 5 個以上洗い出した
- [ ] 各アクセスパターンに対するキー設計を検証
- [ ] ホットパーティション対策を実装
- [ ] GSI/LSI の個数と用途を確定
- [ ] TTL の必要性を検討
- [ ] 容量予測(読み取り/書き込み)を実施
- [ ] コスト見積り(オンデマンド vs プロビジョンド)
- [ ] セキュリティ要件を確認(KMS、VPC Endpoint)
- [ ] バックアップ・復旧計画を策定
- [ ] グローバルテーブル要否を判定
実装フェーズ
- [ ] DynamoDB Local で開発環境構築
- [ ] SDK(Boto3 / JavaScript 等)を選定
- [ ] CRUD 操作を実装・テスト
- [ ] エラーハンドリング(スロットリング、条件失敗)を実装
- [ ] ロギング・監視(CloudWatch)を設定
- [ ] 単体テスト・統合テストを作成
- [ ] 負荷テスト(k6)を実施
- [ ] パフォーマンスプロファイリング
- [ ] セキュリティスキャン(IAM ポリシー検証)
運用フェーズ
- [ ] CloudWatch ダッシュボードを作成
- [ ] アラート設定(ConsumedCapacity、Throttling)
- [ ] 定期バックアップを検証
- [ ] ポイントインタイムリカバリをテスト
- [ ] コスト分析レポートを月次作成
- [ ] キャパシティプランニング(容量予測)を実施
- [ ] セキュリティレビューを実施
- [ ] ドキュメント更新
まとめ
DynamoDB は 「フルマネージド・スケーラブル・ミリ秒レイテンシー」 を実現する NoSQL DB です。以下の用途で最適:
✅ DynamoDB を選ぶべき場合:
- 秒間数万~数百万リクエストの大規模トラフィック
- スキーマ変更が頻繁(スキーマレス設計)
- グローバルサービス(複数リージョンで読み書き)
- 運用管理を最小化したい
- コスト対効果を重視
❌ DynamoDB を避けるべき場合:
- 複雑な JOIN が必須(→ Aurora / RDS)
- 関連データの複合クエリが多い(→ RDS)
- トランザクション ACID が強く必須(→ Aurora DSQL / RDS)
- データウェアハウス用途(→ Redshift)
キー設計が 90% を占める ため、十分なアクセスパターン分析と反復的な設計見直しが成功のポイント。AWS Well-Architected Framework / Single Table Design パターンの学習をお勧めします。
参考文献
- AWS DynamoDB 公式ドキュメント
- DynamoDB Developer Guide
- DynamoDB Best Practices
- Amazon DynamoDB Global Tables - Multi-Account Replication
- 2026 年 2 月:複数 AWS アカウント間レプリケーション対応
- DynamoDB Standard-IA Storage Class
- 2026 年:低頻度アクセスで 60% ストレージコスト削減
- AWS Well-Architected Framework - Database Design
- AWS Database Blog - DynamoDB Articles
- 最新機能・パフォーマンス・セキュリティ記事
- Alex DeBrie - The DynamoDB Book
- Single Table Design by Rick Houlihan
- DynamoDB Design Patterns
- AWS re:Invent 2024 - DynamoDB Sessions
- Serverless Application Lens - AWS Well-Architected
- AWS SDK Documentation - DynamoDB
- NoSQL Workbench for DynamoDB
- ローカルテーブル設計・可視化ツール
- PartiQL for DynamoDB
- SQL ライク構文でのテーブルクエリ
最終更新:2026-04-26