Amazon Web Services ブログ

Amazon DynamoDB から Amazon S3 へのフィルター付きエクスポート機能のご紹介

本記事は 2026 年 10 月 1 日に公開された “Introducing filtered export from Amazon DynamoDB to Amazon S3” を翻訳したものです。

本日、Amazon DynamoDB のフィルター付きエクスポート機能をリリースしました。これにより、テーブルのキャパシティを消費することなく、必要な項目と属性のみをエクスポートできるようになりました。Amazon Simple Storage Service (Amazon S3) へのエクスポートは、2020 年のリリース以来、テーブル内のすべての項目を書き出してきました。2023 年に追加された増分エクスポートは、特定の時間枠内で変更されたすべての項目を書き出します。

フィルター付きエクスポートでは、同じ ExportTableToPointInTime リクエストに FilterSpecification が追加され、必要なアイテムと属性のみを取得するための式を指定できます。エクスポートは、一致するデータを S3 に書き込みます。テーブルではなく、ポイントインタイムリカバリ (PITR) バックアップから読み取るため、テーブルキャパシティを消費せず、本番トラフィックにも影響を与えません。

本投稿では、フィルター付きエクスポートを紹介し、問題のあるデプロイの後に単一テナントのデータを復旧するために、4 TB 丸ごとリストアするのではなく 1 回の増分エクスポートで行う方法を解説します。さらに 2 つのパターンを示します。1 つは顧客連絡先属性を除外したテナント履歴の共有、もう 1 つは特定時点のエクスポートと S3 インポートを使用した別リージョンへのテナント移行です。

DynamoDB の Amazon S3 へのエクスポートの概要

Amazon DynamoDB は、サーバーレスでフルマネージドな分散型 NoSQL データベースで、どのような規模でも 1 桁ミリ秒のパフォーマンスを実現します。Amazon S3 へのエクスポートは PITR バックアップから読み込むため、どのような規模のエクスポートでも読み込みキャパシティーを消費せず、アプリケーションのスループットと競合することもありません。

フル (非増分) エクスポートでは、PITR ウィンドウ内の特定の時点に存在していたすべての項目が書き込まれます。PITR ウィンドウは最大 35 日間まで遡ることができます。増分エクスポートでは、少なくとも 15 分、最大 24 時間離れた 2 つの時点の間で変更された項目が書き込まれ、各項目の新しいイメージと、オプションで古いイメージが含まれます。

どちらも改行区切りの DynamoDB JSON または Amazon Ion をバケットに書き込み、エクスポートの内容を記述した manifest-summary.json ファイルと、サービスが生成したエクスポート ID 配下に、各データファイルをアイテム数とチェックサムとともに一覧表示する manifest-files.json ファイルを出力します。Amazon Athena は圧縮されたデータファイルを直接読み取るため、データフォルダ上にテーブル定義を作成するだけで、SQL でエクスポートをクエリできます。

フィルター付きエクスポートのご紹介

これまで、エクスポートの単位はテーブルでした。数百のテナントを保持するマルチテナントテーブルから 1 つのテナントを復元するには、すべてをエクスポートしてから後段でサブセットを選択するか、テナントのパーティションに対して Query を実行して現在の状態のみを取得する必要がありました。

フィルター付きエクスポートは、選択条件をエクスポートリクエストに移します。このリクエストには、Query や Scan ですでに使用している式構文を利用した 5 つのフィールドを持つ FilterSpecification オブジェクトが追加されます。

フィールド 役割
KeyConditionExpression Query のセマンティクスに従って、1 つのパーティションキー値を選択し、オプションでソートキー条件を指定します。エクスポートが読み取るパーティションを制限するため、エクスポートで処理されるデータが少なくなります。
FilterExpression Scan で使用する演算子を用いて、キー属性と非キー属性の両方に条件を指定します。読み取り後に各アイテムに適用されるため、処理されるデータ量を削減せずに、書き込む内容を選択します。キー属性は、KeyConditionExpression が指定されていない場合にのみ指定できます。
ProjectionExpression 書き込む属性の名前を指定します。
ExpressionAttributeNames 属性名の置換トークンです。この記事の例では、Status などの名前は予約語であるため、すべての名前にエイリアスを設定しています。
ExpressionAttributeValues 属性値の置換トークンです。

キー条件式は Query で記述するものと同じですが、2 つの操作は読み取る対象が異なります。Query は現在のテーブルを 1 ページずつ読み取り、読み取りキャパシティーを消費します。一方、フィルター付きフルエクスポートは、選択した時点の PITR バックアップを読み取り、その時点でのパーティションを返します。フィルター付き増分エクスポートは、指定した期間内に変更された項目を返し、各項目について期間開始前と終了時点の状態を含めます。結果は S3 に書き込まれ、同一アカウントでも別アカウントでも可能で、テーブルキャパシティーを消費せず、ページネーションやアップロードのコードを書く必要もありません。

フィルタリングは、フルエクスポートと増分エクスポートの両方に適用できます。ExportType で FULL_EXPORT または INCREMENTAL_EXPORT を選択し、FilterSpecification で対象の項目と属性を選択します。DescribeExport は適用された FilterSpecification を返し、フィルター付きエクスポートはフルエクスポートと同じ AWS Identity and Access Management (IAM) 権限を使用します。

次のスクリーンショットは、DynamoDB コンソールでエクスポートをリクエストする際のフィルターオプションを示しています。

DynamoDB のエクスポートリクエスト画面にあるフィルター指定のオプション。キー条件式、フィルター式、プロジェクション式の入力欄がある

図 1: Amazon DynamoDB コンソールにおけるポイントインタイムエクスポートのフィルターオプション

前提条件

この記事を進めるには、以下の前提条件を満たしている必要があります。

  • PITR が有効な DynamoDB テーブルを持つ AWS アカウント。この例では、米国東部 (バージニア北部) リージョン (us-east-1) にある FieldServiceData という名前のテーブルを使用します。
  • この例では、amzn-s3-demo-bucket と、移動先として欧州 (アイルランド) リージョン (eu-west-1) にある 2 つ目のバケット amzn-s3-demo-destination-bucket を使用します。
  • テーブルからのエクスポートとバケットへの書き込みを許可する認証情報が設定された AWS Command Line Interface (AWS CLI)。
  • 影響評価セクションのための Amazon Athena へのアクセス。

問題のあるデプロイ後の特定のテナントの復旧

AnyCompany Field Ops は、顧客企業のフィールドサービス作業指示書を管理する SaaS (software as a service) プロバイダーです。1 つの DynamoDB テーブル FieldServiceData が、すべてのテナントの作業指示書を保持しています。TenantId がパーティションキーで、WorkOrderId がソートキーです。各アイテムは、Status、Priority、CustomerEmail、CustomerPhone、AmountDue (セント単位)、および UpdatedAt (アプリケーションが書き込みのたびに付与する ISO 8601 形式のタイムスタンプ) を保持しています。テーブルは数百のテナントにまたがり、約 4 TB です。

9 月 10 日 13:55 UTC、チームは請求照合サービスの新バージョンをデプロイします。これには、まず tenant-4213 に対して実行するようフラグが設定されたデータ移行ジョブが含まれています。ジョブは 14:02 UTC に開始されます。不具合により、AmountDue が誤った乗数で再計算され、アクティブなワークオーダーに対して Status が COMPLETED に設定されてしまいます。14:42 UTC、テナントは残高の誤りとクローズされたワークオーダーを報告します。オンコールエンジニアがジョブを停止し、14:50 UTC までにロールバックが完了します。tenant-4213 に属する約 48,000 件のアイテムが誤った値を保持することになり、他のテナントには影響がありませんでした。

チームは、ジョブの最初の書き込みが行われる前の 14:00 UTC 時点における tenant-4213 のアイテムを必要としています。PITR リストアを実行すると、テーブルの 4 TB のコピーが作成されますが、そのうちテナントに属するのは約 2 GB です。テナントのパーティションに対する Query は、現在の状態のアイテムを返します。破損が発生した時間帯に対する増分エクスポートでは、NEW_IMAGE と OLD_IMAGE、およびテナントのパーティションキーをキー条件式として使用します。これにより、14:00 から 14:45 UTC の間に変更されたテナントのアイテムのみが、時間帯開始前の状態と時間帯終了時点の状態と共に書き出されます。1 回のエクスポートで、影響を受けたアイテム群とインシデント発生前のコピーの両方を取得できます。

エクスポートのリクエスト

以下の AWS CLI コマンドでエクスポートをリクエストします。ウィンドウは UTC の 14:00 から 14:45 までで、ジョブの書き込みをカバーし、増分エクスポートに必要な最低 15 分の要件を満たしています。キー条件はテナントのパーティションキーを選択し、リカバリには完全なアイテムが必要なため、リクエストにはフィルターやプロジェクションは含まれません:

aws dynamodb export-table-to-point-in-time \
  --table-arn arn:aws:dynamodb:us-east-1:111122223333:table/FieldServiceData \
  --export-type INCREMENTAL_EXPORT \
  --incremental-export-specification '{
    "ExportFromTime": "2026-09-10T14:00:00Z",
    "ExportToTime": "2026-09-10T14:45:00Z",
    "ExportViewType": "NEW_AND_OLD_IMAGES"
  }' \
  --s3-bucket amzn-s3-demo-bucket \
  --s3-prefix exports/tenant-4213-recovery/ \
  --export-format DYNAMODB_JSON \
  --client-token tenant-4213-recovery-20260910 \
  --filter-specification '{
    "KeyConditionExpression": "#tid = :tid",
    "ExpressionAttributeNames": {"#tid": "TenantId"},
    "ExpressionAttributeValues": {":tid": {"S": "tenant-4213"}}
  }'

エクスポートステータスの確認

ExportTableToPointInTime は ExportArn を返し、エクスポートはバックグラウンドで実行されます。DescribeExport はステータスを報告します:

aws dynamodb describe-export \
  --export-arn arn:aws:dynamodb:us-east-1:111122223333:table/FieldServiceData/export/01789052952000-1a2b3c4d

レスポンスには両方の仕様が反映されています。

{
  "ExportDescription": {
    "ClientToken": "tenant-4213-recovery-20260910",
    "DestinationType": "S3",
    "EndTime": "2026-09-10T15:24:03.985000+00:00",
    "ExportArn": "arn:aws:dynamodb:us-east-1:111122223333:table/FieldServiceData/export/01789052952000-1a2b3c4d",
    "ExportFormat": "DYNAMODB_JSON",
    "ExportManifest": "exports/tenant-4213-recovery/AWSDynamoDB/01789052952000-1a2b3c4d/manifest-summary.json",
    "ExportStatus": "COMPLETED",
    "ExportType": "INCREMENTAL_EXPORT",
    "FilterSpecification": {
      "ExpressionAttributeNames": {"#tid": "TenantId"},
      "ExpressionAttributeValues": {":tid": {"S": "tenant-4213"}},
      "KeyConditionExpression": "#tid = :tid"
    },
    "IncrementalExportSpecification": {
      "ExportFromTime": "2026-09-10T14:00:00+00:00",
      "ExportToTime": "2026-09-10T14:45:00+00:00",
      "ExportViewType": "NEW_AND_OLD_IMAGES"
    },
    "ItemCount": 48627,
    "S3Bucket": "amzn-s3-demo-bucket",
    "S3Prefix": "exports/tenant-4213-recovery/",
    "S3SseAlgorithm": "AES256",
    "StartTime": "2026-09-10T15:09:12+00:00",
    "TableArn": "arn:aws:dynamodb:us-east-1:111122223333:table/FieldServiceData",
    "TableId": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
  }
}

ItemCount は、ウィンドウ内で変更された tenant-4213 の項目数であり、テーブルやテナントの項目数ではありません。

Amazon S3 での出力の確認

エクスポートでは増分エクスポートのレイアウトが使用され、マニフェストはエクスポート ID フォルダ配下に、データファイルはプレフィックス配下の data フォルダに配置されます:

s3://amzn-s3-demo-bucket/exports/tenant-4213-recovery/AWSDynamoDB/
    01789052952000-1a2b3c4d/
        _started
        manifest-files.json
        manifest-files.md5
        manifest-summary.json
        manifest-summary.md5
    data/
        6nrravgomiyjpnjumsmzc3w2ve.json.gz
        du5kedq3ee7dlbixg2crj4pawe.json.gz
        ...

各データファイルの各行は、ウィンドウ内で変更された tenant-4213 の 1 つの項目を表しており、OldImage (14:00 UTC 直前の状態) と NewImage (ウィンドウ終了時の状態) が含まれています。以下のレコードはそのような項目の 1 つで、読みやすさのために複数行にフォーマットされています。

{
  "Metadata": {"WriteTimestampMicros": {"N": "1789049381000000"}},
  "Keys": {"WorkOrderId": {"S": "WO-0010041"}, "TenantId": {"S": "tenant-4213"}},
  "OldImage": {
    "WorkOrderId": {"S": "WO-0010041"}, "TenantId": {"S": "tenant-4213"},
    "CustomerPhone": {"S": "+1-206-555-0142"}, "Priority": {"S": "URGENT"},
    "CustomerEmail": {"S": "diego_ramirez@example.com"}, "UpdatedAt": {"S": "2026-09-09T22:17:03Z"},
    "AmountDue": {"N": "48250"}, "Status": {"S": "IN_PROGRESS"}
  },
  "NewImage": {
    "WorkOrderId": {"S": "WO-0010041"}, "TenantId": {"S": "tenant-4213"},
    "CustomerPhone": {"S": "+1-206-555-0142"}, "Priority": {"S": "URGENT"},
    "CustomerEmail": {"S": "diego_ramirez@example.com"}, "UpdatedAt": {"S": "2026-09-10T14:09:41Z"},
    "AmountDue": {"N": "4825000"}, "Status": {"S": "COMPLETED"}
  }
}

OldImage がないレコードはウィンドウ内で作成された項目であり、NewImage がないレコードは削除を示します。他のテナントのデータは含まれないため、このリカバリ用プレフィックスをインシデント対応チームと共有できます。

Amazon Athena による影響の評価

以下の Athena ステートメントは、エクスポートデータに対してテーブルを定義します。各イメージカラムは DynamoDB JSON 構造を反映しており、すべての属性はフィールド名が型記述子となる構造体 (struct) です:

CREATE EXTERNAL TABLE tenant_4213_window (
  Metadata struct<WriteTimestampMicros:struct<N:string>>,
  Keys     struct<TenantId:struct<S:string>, WorkOrderId:struct<S:string>>,
  OldImage struct<
    Status:struct<S:string>, Priority:struct<S:string>,
    AmountDue:struct<N:string>, UpdatedAt:struct<S:string>
  >,
  NewImage struct<
    Status:struct<S:string>, Priority:struct<S:string>,
    AmountDue:struct<N:string>, UpdatedAt:struct<S:string>
  >
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://amzn-s3-demo-bucket/exports/tenant-4213-recovery/AWSDynamoDB/data/';

次のクエリでは、ウィンドウ内のテナント自身のアクティビティとジョブによる書き込みを分離します。ジョブは Status を COMPLETED に設定し、AmountDue を乗算したため、Status が COMPLETED に変更され、同時に AmountDue も変更されたレコードは破損の痕跡を示しています。どちらか一方のみが変更された更新や、OldImage のない挿入は、通常のアプリケーショントラフィックです。

SELECT
  Keys.WorkOrderId.S                        AS work_order_id,
  OldImage.Status.S                         AS status_before,
  CAST(OldImage.AmountDue.N AS bigint)      AS amount_before,
  CAST(NewImage.AmountDue.N AS bigint)      AS amount_now,
  NewImage.UpdatedAt.S                      AS written_at
FROM tenant_4213_window
WHERE OldImage IS NOT NULL
  AND NewImage IS NOT NULL
  AND NewImage.Status.S = 'COMPLETED'
  AND OldImage.Status.S <> 'COMPLETED'
  AND OldImage.AmountDue.N <> NewImage.AmountDue.N;

その結果が、修復対象の作業指示のリストとなります。ライトバックのステップではコード内で同じシグネチャが適用されるため、このクエリは本番環境へ書き込まれる前のレビューとして機能します。

インシデント発生前の項目の書き戻し

以下のスクリプトは、エクスポートのデータファイルを S3 からストリーミングで読み込み、破損の兆候を持つレコードを選別し、各 OldImage を PutItem で書き戻します。条件式により、UpdatedAt が破損ウィンドウ内に収まっている場合にのみアイテムが置き換えられます。ロールバック後に顧客やアプリケーションが更新した作業指示書はそのまま残されます。

"""Write pre-incident items back for the work orders the deployment changed."""
import gzip
import json

import boto3

BUCKET = "amzn-s3-demo-bucket"
DATA_PREFIX = "exports/tenant-4213-recovery/AWSDynamoDB/data/"
TABLE = "FieldServiceData"
WINDOW_START = "2026-09-10T14:02:00Z"
WINDOW_END = "2026-09-10T14:42:00Z"

s3 = boto3.client("s3", region_name="us-east-1")
ddb = boto3.client("dynamodb", region_name="us-east-1")


def export_records():
    pages = s3.get_paginator("list_objects_v2").paginate(Bucket=BUCKET, Prefix=DATA_PREFIX)
    for page in pages:
        for obj in page.get("Contents", []):
            if not obj["Key"].endswith(".json.gz"):
                continue
            body = s3.get_object(Bucket=BUCKET, Key=obj["Key"])["Body"]
            with gzip.GzipFile(fileobj=body) as gz:
                for line in gz:
                    yield json.loads(line)


def corrupted(record):
    old, new = record.get("OldImage"), record.get("NewImage")
    if old is None or new is None:
        return False  # insert or delete inside the window: not the job's work
    return (
        new["Status"]["S"] == "COMPLETED"
        and old["Status"]["S"] != "COMPLETED"
        and old["AmountDue"]["N"] != new["AmountDue"]["N"]
    )


restored = skipped = 0
for record in filter(corrupted, export_records()):
    try:
        ddb.put_item(
            TableName=TABLE,
            Item=record["OldImage"],
            ConditionExpression="#ua BETWEEN :ws AND :we",
            ExpressionAttributeNames={"#ua": "UpdatedAt"},
            ExpressionAttributeValues={":ws": {"S": WINDOW_START}, ":we": {"S": WINDOW_END}},
        )
        restored += 1
    except ddb.exceptions.ConditionalCheckFailedException:
        skipped += 1

print(f"restored {restored}, skipped {skipped}")

PutItem はアイテム全体を置き換えるため、部分的な失敗の後にスクリプトを再実行しても、追加の管理処理なしで同じ最終状態に収束します。以下の出力は、同じインシデントをシードした小さなテーブルに対して連続して 2 回実行した結果です。2 回目の実行では、復元されたすべてのアイテムが再度対象期間前の UpdatedAt を保持していることが確認されるため、条件チェックに失敗し、何も書き込まれません。

restored 3, skipped 0
restored 0, skipped 3

古いイメージはウィンドウ開始前の項目の状態です。written_at がジョブの書き込み時刻のいずれでもないレコードは、ウィンドウ内で他の処理によっても変更されています。一括書き戻しの前にそれらを確認してください。

選択した属性を使用した 1 つのテナントの履歴の共有

AnyCompany Field Ops は、パートナー分析チームに tenant-7788 の作業指示履歴を提供することに合意します。この合意では顧客の連絡先情報は対象外です。ProjectionExpression で書き出す属性を指定することで、CustomerEmail と CustomerPhone は共有バケットに到達することがありません:

aws dynamodb export-table-to-point-in-time \
  --table-arn arn:aws:dynamodb:us-east-1:111122223333:table/FieldServiceData \
  --s3-bucket amzn-s3-demo-bucket \
  --s3-prefix exports/tenant-7788-partner-share/ \
  --export-format DYNAMODB_JSON \
  --client-token tenant-7788-partner-share-20260910 \
  --filter-specification '{
    "KeyConditionExpression": "#tid = :tid",
    "ProjectionExpression": "#tid, #wo, #st, #pri, #amt, #ua",
    "ExpressionAttributeNames": {
      "#tid": "TenantId",
      "#wo": "WorkOrderId",
      "#st": "Status",
      "#pri": "Priority",
      "#amt": "AmountDue",
      "#ua": "UpdatedAt"
    },
    "ExpressionAttributeValues": {":tid": {"S": "tenant-7788"}}
  }'

エクスポートされた各項目には、投影された 6 つの属性のみが含まれ、それ以外は含まれません。

{"Item":{"AmountDue":{"N":"18250"},"Priority":{"S":"URGENT"},"Status":{"S":"IN_PROGRESS"},"TenantId":{"S":"tenant-7788"},"UpdatedAt":{"S":"2026-09-12T09:15:40Z"},"WorkOrderId":{"S":"WO-0081120"}}}

プロジェクションはインクルードリストです。共有する項目を指定し、除外した属性はバケットに届くことはありません。値を検査するわけではないため、個人情報を含むフリーテキストフィールドは、除外しない限りそのまま通過します。宛先バケットは、別のアカウントや別のリージョンに配置することもできます。

1 つのテナントを別リージョンへ移行する

AnyCompany Field Ops のあるテナントが事業拠点をヨーロッパに移転し、データもヨーロッパで保持するよう依頼してきました。特定の時点のフィルター付きフルエクスポートにより、該当テナントのアイテムが eu-west-1 のバケットに書き出され、S3 からのインポートで同リージョンのテーブルにロードされます。他のテナントは現状のまま維持されます。次のコマンドは、合意された切り替え時刻時点のテナントデータを eu-west-1 のバケットにエクスポートします。

aws dynamodb export-table-to-point-in-time \
  --table-arn arn:aws:dynamodb:us-east-1:111122223333:table/FieldServiceData \
  --export-time 2026-09-14T00:00:00Z \
  --s3-bucket amzn-s3-demo-destination-bucket \
  --s3-prefix exports/tenant-5501-relocation/ \
  --export-format DYNAMODB_JSON \
  --client-token tenant-5501-relocation-20260914 \
  --filter-specification '{
    "KeyConditionExpression": "#tid = :tid",
    "ExpressionAttributeNames": {"#tid": "TenantId"},
    "ExpressionAttributeValues": {":tid": {"S": "tenant-5501"}}
  }'

出力はフルエクスポートのレイアウトに従います。すべてのデータファイルはエクスポート ID のフォルダ配下に配置され、各行には Item フィールドでラップされた 1 つのアイテムが格納されます。プロジェクションがないため、すべての属性が含まれます。

以下のコマンドは、エクスポートを eu-west-1 の新しいテーブルにインポートします。S3 からのインポート機能は DynamoDB JSON のエクスポートファイルを直接読み取り、指定されたキースキーマでテーブルを作成します。

aws dynamodb import-table \
  --region eu-west-1 \
  --s3-bucket-source S3Bucket=amzn-s3-demo-destination-bucket,S3KeyPrefix=exports/tenant-5501-relocation/AWSDynamoDB/01789376400000-5e6f7a8b/data/ \
  --input-format DYNAMODB_JSON \
  --input-compression-type GZIP \
  --table-creation-parameters '{
    "TableName": "FieldServiceData",
    "AttributeDefinitions": [
      {"AttributeName": "TenantId", "AttributeType": "S"},
      {"AttributeName": "WorkOrderId", "AttributeType": "S"}
    ],
    "KeySchema": [
      {"AttributeName": "TenantId", "KeyType": "HASH"},
      {"AttributeName": "WorkOrderId", "KeyType": "RANGE"}
    ],
    "BillingMode": "PAY_PER_REQUEST"
  }'

S3 からのインポートでは新しいテーブルが作成されるため、グローバルセカンダリインデックスは TableCreationParameters で宣言します。エクスポート時刻からカットオーバーまでの間に us-east-1 に到達したテナントの書き込みについては、トラフィックを切り替える前にアプリケーション側で再適用または処理しきる必要があります。テナントのアイテムは、アプリケーションが削除するまでソーステーブルに残ります。

料金

フィルター付きエクスポートは、フルエクスポートおよび増分エクスポートと同じ料金体系で、GB あたりの単価も同じであり、フィルタリングに対する追加料金は発生しません。フィルター付きエクスポートは、同じテーブルのフルエクスポートよりも低コストになる可能性があります。キー条件式がパーティションキーを指定している場合、エクスポートはテーブル全体ではなく、そのキーを含むパーティションのみを読み取ります。課金はマッチしたデータに対して行われますが、現在のエクスポートに適用されている 1 回のエクスポートあたり 10 MB の最小課金対象データ量が適用されます。キー以外の属性に対するフィルターは、エクスポートが読み取るデータを削減しません。

Amazon S3 では、エクスポートが書き込むオブジェクトのストレージとリクエストが課金され、Amazon Athena ではスキャンされたバイト数に応じて課金されます。リカバリエクスポートは、45 分間のウィンドウで変更されたテナントのアイテム (それぞれ 2 つのイメージ (変更前と変更後) を含む) を保持しますが、同じウィンドウのフィルターなしの増分エクスポートでは、すべてのテナントの変更が保持されます。リロケーションエクスポートはそのテナントの 2 GB を保持しますが、フルエクスポートでは 4 TB のテーブル全体が書き込まれることになります。エクスポートはテーブルの読み取りキャパシティを消費しません。フィルター付きエクスポートに必要な PITR 継続的バックアップは、標準の PITR 料金で課金されます。

考慮事項

以下の点に注意してください。

  • フルエクスポートと同じ要件として、ソーステーブルで PITR を有効にする必要があります。エクスポートは PITR ウィンドウ内の任意の時点を対象にでき、PITR ウィンドウは最大 35 日間に及びます。
  • キー条件式は Query のセマンティクスに従います。パーティションキーの値を 1 つ、等価条件のみで指定し、オプションでソートキー条件を指定できます。フィルター式は読み取り後に適用されるため、エクスポートが処理するデータ量を減らすことなく、書き込まれる内容を選択します。
  • キー条件式で許可されていない非等価条件をパーティションキーに適用したい場合は、代わりにフィルター式で表現してください。フィルター式は、キー条件式でそのキーが使用されていない場合に限り、パーティションキーまたはソートキーの属性を参照できます。
  • フィルター付きエクスポートは、リリース時点ではセカンダリインデックスでは動作しません。これはフルエクスポートと同様です。
  • エクスポートはフルエクスポートと同じ一貫性モデルを持ちます。リクエストされた時刻までのすべての書き込みがパーティション間で結果整合性をもってキャプチャされ、エクスポートはトランザクションを認識しません。
  • フルエクスポートと同じモデルに従い、クロスアカウントおよびクロスリージョンの宛先がサポートされます。

クリーンアップ

継続的な料金が発生しないように、この記事で作成したリソースを削除してください。DynamoDB は、バケットからエクスポート出力を削除することはありません。以下のコマンドでエクスポートされたオブジェクトを削除します:

aws s3 rm s3://amzn-s3-demo-bucket/exports/tenant-4213-recovery/ --recursive
aws s3 rm s3://amzn-s3-demo-bucket/exports/tenant-7788-partner-share/ --recursive
aws s3 rm s3://amzn-s3-demo-destination-bucket/exports/tenant-5501-relocation/ --recursive

以下のステートメントは、メタデータのみを保持する Athena テーブルを削除します:

DROP TABLE tenant_4213_window;

本手順に沿うためだけに作成した場合は、以下のコマンドで eu-west-1 のインポート済みテーブルを削除します:

aws dynamodb delete-table --region eu-west-1 --table-name FieldServiceData

この投稿用にソーステーブルを作成した場合は、同様に削除するか、PITR を無効化してください。PITR は有効化されている間、標準料金で課金が継続されるためです。エクスポートタスクのメタデータは、90 日後に DescribeExport および ListExports から取得できなくなります。

まとめ

本記事では、エクスポートを 1 つのパーティションキー、条件に合致するアイテム、選択した属性セットに絞り込めるフィルター付きエクスポートを紹介しました。4 TB のテーブルから、障害発生期間にわたる 1 回の増分エクスポートで単一テナントのアイテムを復旧し、変更されたアイテムとインシデント前の状態を同時に取得できました。それらを Amazon Athena で確認し、条件付き PutItem で古いイメージを書き戻しました。同じ形式のリクエストで、選択した属性のみを使ってテナントの履歴を共有したり、特定時点のエクスポートと S3 インポートを用いてテナントを別のリージョンへ移行することもできます。

フィルター付きエクスポートは、すべての商用リージョンでご利用いただけます。使用を開始するには、Amazon S3 への DynamoDB データのエクスポート を参照してください。また、どのようなデータをエクスポートしているか、コメントでお知らせください。

著者について

Lee Hannigan

Lee Hannigan

Lee はアイルランドのドニゴールを拠点とするシニア Amazon DynamoDB データベースエンジニアです。ビッグデータと分析技術の強固な基盤に支えられた、分散システムに関する豊富な専門知識を有しています。

Anugrah Prakash

Anugrah Prakash

Anugrah はシアトルを拠点とする Amazon DynamoDB チームのシニアプロダクトマネージャーです。テクノロジーとプロダクトマネジメントのバックグラウンドを持ち、お客様と密に協力して長期的な価値を提供する機能を定義することを楽しんでいます。仕事以外では、旅行、ハイキング、テクノロジーに関する読書を楽しんでいます。


翻訳は Solutions Architect の Hayato Tsutsumi が担当しました。