AWS DVA / 第3章

CHAPTER 03 / D1 / D4

DynamoDB とデータストア

キー、インデックス、整合性、S3の使い方を学ぶ。

一読の目安 35分図・具体例・確認問題

01 / 保存先はアクセスパターンで選ぶ

「データを保存できる」だけでは選べません。何をキーに検索するか、結合やトランザクションが必要か、オブジェクト全体を取得するかを考えます。

サービス向いている例判断の軸
DynamoDB注文IDで取得、顧客ごとの注文一覧キーによるアクセス、低レイテンシ、スケール
S3写真、CSV、ビルド成果物オブジェクトをキーで保存・取得
RDS / Aurora複数テーブルのSQL・JOIN関係性とSQL、接続数、トランザクション
ElastiCacheセッション、汎用の高速キャッシュTTL、失効、キャッシュミス、メモリ容量
DAXDynamoDBの読み取りキャッシュDynamoDB互換のアクセスを高速化。強い整合性を要求する読み取りはキャッシュを使わない

02 / DynamoDBのキーとインデックス

主キーはパーティションキーだけ、またはパーティションキー+ソートキーで構成します。複合キーの場合、組み合わせが項目を一意にします。同じパーティションキーの項目を、ソートキーの範囲で取得できます。

たとえば、主キーをPK=CUSTOMER#123、SK=ORDER#2026-11-08#001とすれば、顧客の注文を時系列に探す形を作れます。全注文を一つの固定値のパーティションキーに集中させると、ホットパーティションの原因になります。キーの種類の多さだけでなく、アクセス量の偏りも見ます。

GSIは別の検索入口ベーステーブルは顧客と注文日時で検索し、GSIは注文状態と注文日時で検索します。GSIの更新は非同期なので、最新状態を直ちに読む用途とは区別します。ベーステーブルPK: customerIdGSIPK: statusSK: createdAtSK: createdAt非同期に反映「顧客123の注文」をQuery「PENDINGの注文」をQuery
GSIは別の検索入口 — ベーステーブルは顧客と注文日時で検索し、GSIは注文状態と注文日時で検索します。GSIの更新は非同期なので、最新状態を直ちに読む用途とは区別します。
比較GSILSI
パーティションキーベーステーブルと異なるキーを選べるベーステーブルと同じ
ソートキーベーステーブルと異なる構成にできる別のソートキー
作成のタイミング作成時・作成後に追加可能テーブル作成時に定義
読み取り整合性結果整合性のみ結果整合性 / 強い整合性
容量ベーステーブルと別に管理するベーステーブルの容量を共有

公式資料:セカンダリインデックス

03 / Query・Scan・整合性

Queryはパーティションキーの等価条件が必須です。ソートキーには範囲・前方一致などの条件を追加できます。任意の属性を自由にSQL検索する仕組みではないため、検索入口がなければGSIなどを検討します。

Scanはテーブルやインデックスを読み進めます。FilterExpressionは読み取り後に結果を絞るので、返却件数を減らしても読み取り容量の節約には直結しません。Queryのフィルターにも同じ注意が当てはまります。

boto3:Query とページング(処理の抜粋)
from boto3.dynamodb.conditions import Key

params = {"KeyConditionExpression": Key("customerId").eq("C123")}
while True:
    page = table.query(**params)
    for item in page.get("Items", []):
        print(item["orderId"])
    last_key = page.get("LastEvaluatedKey")
    if not last_key:
        break
    params["ExclusiveStartKey"] = last_key

Query/Scanは一回の呼び出しで全件返るとは限りません。LastEvaluatedKeyがあれば続きを取得します。フィルターで返却件数が0でも続きがある場合があります。

公式資料:読み取り整合性

04 / 容量の計算を一度やってみる

オンデマンドはリクエストに応じた課金、プロビジョンドは設定した容量を軸とする課金です。予測しにくい負荷と、安定して予測できる負荷を区別します。どちらもキーへの偏りやサービスクォータを無視できるわけではありません。

学習用の基本例。インデックス、トランザクション、操作の種類による追加消費は別に考えます。
通常の単一項目操作1単位で扱う量計算例
強い整合性の読み取り1 RCU = 4 KB以下を毎秒1回6 KBを毎秒10回 → ceil(6/4) × 10 = 20 RCU
結果整合性の読み取り強い整合性の半分の読み取り単位6 KBを毎秒10回 → 2 × 10 ÷ 2 = 10 RCU
通常の書き込み1 WCU = 1 KB以下を毎秒1回1.5 KBを毎秒20回 → ceil(1.5/1) × 20 = 40 WCU

サイズは境界ごとに切り上げます。トランザクション操作は通常の操作より容量を消費します。GSIへの書き込みや、読み取り対象と実際のサイズにも注意してください。

公式資料:RCU・WCU

05 / 条件付き更新・トランザクション・TTL

要件機能注意点
同じIDを二度作りたくないConditionExpression / attribute_not_exists存在確認と書き込みを別々にすると競合する
同時更新で上書きを防ぐバージョン番号+条件式による楽観的ロック読み取ったversionと一致するときだけ更新
在庫更新と注文作成を両方成功させたいTransactWriteItems同一アカウント・同一リージョン内。BatchWriteItemは全件原子的ではない
期限切れデータを自動で掃除したいTTL期限は秒単位のUnix時刻のNumber。削除は即時ではない
データ変更に応じて後続処理をしたいDynamoDB Streams変更記録を処理。Lambda側は重複を考えて冪等にする
重複作成を防ぐ条件付き書き込み(処理の抜粋)
table.put_item(
    Item={"orderId": "O123", "status": "PENDING"},
    ConditionExpression="attribute_not_exists(orderId)"
)
# 既に存在すれば ConditionalCheckFailedException。
# アプリ側で「既存結果を返す」などの業務上の扱いを決める。

公式資料:TTL の削除タイミング

06 / S3・キャッシュで押さえること

S3はオブジェクトストレージです。一般的なPUT、DELETE後のGET・LISTには強い整合性があります。ただし、CloudFrontなどのキャッシュが古い内容を返す問題は別です。バージョニングは誤更新からの復旧、Lifecycleは保存クラスの移行や期限切れ削除に使います。

大きなファイルはマルチパートアップロードで分割して送れます。失敗した部分だけの再送が可能ですが、未完了パートの管理も必要です。S3のCORSはブラウザのアクセス可否を制御する設定で、IAMやバケットポリシーの代わりにはなりません。

キャッシュよくある使いどころ気をつけること
CloudFront画像や静的コンテンツをエッジで配信キャッシュキー、TTL、無効化、ファイル名のバージョン化
API Gateway REST APIキャッシュAPIの応答を再利用利用者で内容が違うならキーの分離。認可との組み合わせ
ElastiCache汎用データ、セッションキャッシュミス時の正本、TTL、更新時の失効
DAXDynamoDBへの読み取り負荷を軽減強い整合性の読み取りはDynamoDBへ。書き込み経路とキャッシュの鮮度

設計練習:一覧が遅い

全注文に対してScanし、status=PENDINGだけ返すAPIが遅い。キャッシュ以外で改善するなら?

考え方・解答例

statusを検索入口に持つGSIを検討し、Queryできる形にします。ただし、状態の種類が少なくアクセスが一つに集中するなら、キーの分散やアクセスパターンも見直します。フィルター追加だけでは読み取り自体は減りません。

07 / 確認問題

QUESTION 3-1 · 単一選択GSIに書き込み直後の最新状態が出ない。適切な理解は?
解答・解説を読む

正解:B
GSIは強い整合性の読み取りに対応しません。フィルターやTTLはインデックス反映の遅延を解決しません。

QUESTION 3-2 · 単一選択通常の書き込みで、1項目2.2 KBを毎秒10回書く。必要な基本WCUは?
解答・解説を読む

正解:C
1 KB単位で項目サイズを切り上げるため、1回3 WCU、毎秒10回で30 WCUです。インデックス等の追加消費を除く例です。

08 / この章の到達点

上のチェックは、このページでの振り返り用です。章単位の進捗は下のボタンで記録できます。

公式資料

内容確認日:2026年11月8日。仕様の詳細や更新情報は、各公式資料で確認できます。

おつかれさまでした。

理解を確認できたら、章の進捗を記録できます。