AWS Certified Developer - Associate (DVA-C02) #4 Domain 1-3 AWS サービスでの開発 — DynamoDB 開発
#3 API Gateway で関門を整理したので、その後ろのデータです。サーバーレスアプリケーションの基本データベースは DynamoDB です。SAA が「いつ DynamoDB を選ぶか」を問うなら、DVA は一段深く入って 「キーをどう設計し、書き込み競合をどう防ぎ、変更をどう流すか」 をコードレベルで問います。
キー設計 — パーティションキーとソートキー #
DynamoDB のすべてのテーブルは プライマリキー (Primary Key) で項目を識別します。
| キー構成 | 意味 |
|---|---|
| パーティションキーのみ | パーティションキー値がそのまま項目の一意な識別子 |
| パーティションキー + ソートキー | 同じパーティションキーの中でソートキーにより複数項目を整列・範囲照会 |
パーティションキーはデータが物理的に分散される基準 です。特定のキーにトラフィックが集中すると (ホットパーティション)、そのパーティションだけがスロットリングされます。そのため試験は「均等に分散されるパーティションキー」を良い設計とみなします。カーディナリティが高く、アクセスが均等な属性をパーティションキーに選ぶ必要があります。
Query vs Scan #
- Query — パーティションキーで項目を見つけ、ソートキーで範囲を絞ります。効率的です。
- Scan — テーブル全体を読みます。遅くて高コストです。
試験の原則: Scan は避けて Query を使う。 「特定の属性でよく照会する必要があるが、それがキーではない」なら、答えは Scan ではなく インデックス (GSI) です。
LSI vs GSI #
キーでない属性で照会するには補助インデックスが必要です。2 種類の違いは試験の常連です。
| 区分 | LSI (ローカルセカンダリインデックス) | GSI (グローバルセカンダリインデックス) |
|---|---|---|
| パーティションキー | テーブルと 同一 | 異なる 属性が可能 |
| ソートキー | 異なる属性 | 異なる属性 |
| 作成時点 | テーブル作成時のみ | いつでも追加・削除 |
| 整合性 | 強整合性が可能 | 結果整合性のみ |
| キャパシティ | テーブルのキャパシティを共有 | 独自のキャパシティ |
核心を一行で: LSI はテーブル作成時のみ、同じパーティションキー。GSI はいつでも、異なるパーティションキー。 ほとんどの「別の属性で照会」という要求は柔軟な GSI が答えです。LSI は同じパーティションキーの中で別のソート基準が必要で、かつ強整合性が必要なときだけ検討します。
読み込み整合性 #
DynamoDB の読み込みは 2 つの整合性を提供します。
- 結果整合性読み込み (デフォルト) — 最新の書き込みがまだ反映されていない場合がある。コストが半分。
- 強整合性読み込み — 常に最新の値。コスト 2 倍、GSI では不可。
キャパシティモードとスロットリング #
| モード | 適した場合 |
|---|---|
| オンデマンド (On-Demand) | トラフィックが予測不可・断続的。キャパシティ管理が不要 |
| プロビジョニング (Provisioned) | トラフィックが予測可能。RCU/WCU を事前指定、Auto Scaling 可能 |
プロビジョニングモードでキャパシティを超えると ProvisionedThroughputExceededException (スロットリング) が出ます。SDK はデフォルトで 指数バックオフで自動リトライ します。短い瞬間のバーストは適応キャパシティ (adaptive capacity) が一部吸収します。「スロットリングが出る」の答えは通常 キャパシティの引き上げ、キー分散の改善、指数バックオフのリトライ です。
条件付き書き込みと楽観的ロック #
DVA で最も重要な開発パターンです。条件付き書き込み (Conditional Write) は条件が真のときだけ書き込みを実行します。
- 項目がないときだけ作成 —
attribute_not_exists(PK)条件で重複作成を防ぎます (冪等性に活用)。 - 楽観的ロック (Optimistic Locking) — 項目に
version属性を置き、「自分が読んだバージョンと同じときだけ更新」という条件で書き込みます。2 つのクライアントが同時に同じ項目を変更すると一方だけが成功し、もう一方はConditionalCheckFailedExceptionを受けてリトライします。
UpdateItem
SET stock = stock - 1, version = version + 1
ConditionExpression: version = :expectedVersion- アトミックカウンター (Atomic Counter) —
SET views = views + 1のように条件なしで増加させます。競合検証が不要な単純なカウントに適しています。
楽観的ロック = 条件付き書き込み + バージョン属性。同時修正の競合を扱う問題の正解です。
DynamoDB Streams #
テーブルの項目変更 (作成・修正・削除) を時系列で捕捉する変更ログです。
- Lambda を イベントソースマッピング で接続して 変更に反応 します (例: 新しい注文が入ったら通知を送信)。
- ストリームレコードには変更前/後のイメージを含められます (
StreamViewType)。 - グローバルテーブル (マルチリージョンレプリケーション) の基盤でもあります。
「DynamoDB に項目が追加されたら自動的に後続処理をせよ」の答えは Streams + Lambda です。
TTL #
項目に有効期限時刻 (epoch) 属性を指定すると、DynamoDB が期限切れの項目を 自動削除 します。セッション・一時データの整理に使い、削除は即座ではなくバックグラウンドで行われます (通常 48 時間以内)。TTL 削除も Streams で捕捉されます。
DAX #
DynamoDB Accelerator (DAX) は DynamoDB 専用のインメモリキャッシュで、読み込み応答を マイクロ秒 レベルまで下げます。
- 読み込みが非常に多く、レイテンシに敏感なワークロードに適しています。
- アプリケーションコードの変更がほとんどありません (DAX クライアントに置き換え)。
- 汎用キャッシュ (ElastiCache) との区別 が落とし穴です。「DynamoDB の読み込みをマイクロ秒に」は DAX、「汎用インメモリキャッシュ」は ElastiCache です。
試験の出題パターン #
- 「キーでない属性でよく照会する必要がある。」 → GSI (Scan ではない)。
- 「テーブル作成後にインデックスを追加しようとする。」 → GSI (LSI は作成時のみ)。
- 「2 人のユーザーが同時に同じ項目を修正する。競合を防ぐには?」 → 条件付き書き込み + version (楽観的ロック)。
- 「同じ注文が 2 回入っても 1 回だけ作成するには?」 →
attribute_not_exists条件付き書き込み。 - 「項目が追加されたら自動的に後続作業。」 → DynamoDB Streams + Lambda。
- 「
ProvisionedThroughputExceededExceptionが出る。」 → キャパシティの引き上げ・キー分散・指数バックオフ。 - 「DynamoDB の読み込みレイテンシをマイクロ秒に。」 → DAX。
- 「セッションデータを一定時間後に自動削除。」 → TTL。
まとめ #
この記事の要点:
- パーティションキーは分散の基準。均等な分散 = 良いキー。照会は Scan ではなく Query
- LSI (作成時・同じパーティションキー・強整合性) vs GSI (いつでも・異なるパーティションキー・独自キャパシティ・結果整合性)
- 条件付き書き込み + version = 楽観的ロック、
attribute_not_existsは冪等な作成 - Streams + Lambda で変更に反応、TTL で自動期限切れ
- スロットリングはキャパシティ・キー分散・指数バックオフで、読み込みレイテンシは DAX で
次へ — Domain 1-4 メッセージングとイベント #
サーバーレスはコンポーネントを疎に結ぶ 非同期メッセージング で拡張されます。#5 メッセージングとイベント では、SQS (標準 vs FIFO)、SNS、2 つを結合したファンアウト、EventBridge のイベントルーティング、そして Step Functions のワークフローオーケストレーションを見ていきます。