初級読了 5 分

DynamoDB テーブルを CSV にエクスポートする方法(4 つの方法)

DynamoDB にはネイティブの「CSV にエクスポート」ボタンがありません。すべての値は DynamoDB のマーシャリングされた JSON{"S": "..."}{"N": "123"}{"M": {...}} — で包まれて返ってきて、テーブルにはフラットな列の 明白な表現を持たないネストしたマップ、リスト、セットが格納されることがあります。 そのため「DynamoDB を CSV にエクスポート」は実際には 2 つの問題です。アイテムを 取り出す、そして 型付き JSON を行にフラット化する。コンソールもマネージド エクスポートも、2 番目のステップをあなたのためにやってはくれません。

本ガイドでは、テーブルサイズと、アイテムが持つネストの量によって 4 つのアプローチを 順位づけします。

DynamoDB テーブルを CSV にエクスポートするにはどうすればよいですか?

DynamoDB にはネイティブの CSV エクスポート機能がないため、テーブルをスキャンまたはスナップショットし、型付き JSON を行にフラット化する必要があります。小さなテーブルには AWS CLI の scan + jq または短いスクリプトを使い、大きなテーブルは S3 にエクスポートして変換します。フィルタ済みですぐに使える CSV が必要な場合は、DynoTable のような GUI を使用してください。

  • 小さなテーブル、アドホック: AWS CLI scan + jq、または 20 行のスクリプト (方法 1 / 方法 3)。 ネストした属性が現れるまでは問題ありません。
  • 大きなテーブル(GB 以上): DynamoDB の S3 へのエクスポート方法 2)、その後ダンプを変換します。 非同期で実行され、読み取りキャパシティを消費しません — ただし出力は CSV ではなく DynamoDB JSON です。
  • フィルタ / 整形された CSV(列の一部、一部のアイテムのみ): GUI エクスポートか スクリプト。マネージドの S3 エクスポートは テーブル全体 を、フィルタなしで返します。

方法 1: AWS CLI scan + jq

小さなテーブルなら、スキャンして jq で出力を整形できます。Scan はテーブルまたは インデックス内の すべてのアイテム を読み取り、最大 1 MB のページで返します。 CLI はページネーションを自動的にたどります (AWS ドキュメント: テーブルのスキャン)。

aws dynamodb scan --table-name MyTable --output json \
  | jq -r '.Items[] | [.id.S, .name.S, .price.N] | @csv' \
  > out.csv

落とし穴はその jq の行にあります。各属性の 型記述子SNBBOOLMLSSNSBS)の先を掘って生の値を得るために、.id.S.name.S.price.N を 手で書く必要があります。3 つの文字列列を持つフラットなテーブルなら扱えます。 次のものが現れた瞬間に崩壊します。

  • ネストしたマップ / リスト{"M": {...}}{"L": [...]} にはフラット化する 単一の列がありません。@csv が詰まるか、セルを手で JSON エンコードすることになります。
  • セット{"SS": ["a","b"]} はスカラーではなく配列です。
  • 疎な属性 — DynamoDB はスキーマレスなので、アイテム A には price があり、 アイテム B にはないことがあります。固定の列リストは、列を黙って落とすか、ずらします。

また、DynamoDB の型を理解する --output csv はありません。CLI の csv 出力は 生の レスポンスを、記述子もすべて含めてフラット化します — そのため、型タグを剥がすには やはり jq(またはスクリプト)が必要です。これが、「AWS CLI で DynamoDB テーブルを CSV にエクスポート」が自明なケースを超えると決してワンライナーにならない核心的な理由です。

このやり方でより大きなテーブル全体を一日がかりにせずエクスポートするには、--segment / --total-segments でスキャンを並列化し (AWS ドキュメント: パラレルスキャン — DynamoDB は「各アイテムのパーティションキーにハッシュ関数を適用してアイテムを セグメント に 割り当てる」ので、セグメントは不均等になり得ます)、最初の 1 MB ページで止まらないよう ページネーションを読んでください。

方法 2: DynamoDB の S3 へのエクスポート(大きなテーブル)

実際に大きなテーブルには、マネージドの Amazon S3 へのエクスポート が適切なツール です。ポイントインタイムリカバリ(PITR) ウィンドウ内の任意の時点からスナップショットを エクスポートし — そのためテーブルでまず PITR を有効にする必要があります非同期で 実行され、読み取りキャパシティユニットを消費しない ため、テーブルのスループットや 可用性にゼロの影響です(AWS ドキュメント: 「エクスポートは非同期であり、読み取りキャパシティユニット(RCU)を消費せず、テーブルの パフォーマンスと可用性に影響しない」、「エクスポート機能を使うにはテーブルで PITR を 有効にする必要がある」)。これはコンソールの S3 へのエクスポート アクションが内部で トリガーするものでもあります。コンソールは同じ API のフロントエンドにすぎないので、 同じ PITR 要件と同じ JSON 出力を引き継ぎます。

aws dynamodb export-table-to-point-in-time \
  --table-arn arn:aws:dynamodb:us-east-1:123456789012:table/MyTable \
  --s3-bucket my-export-bucket \
  --export-format DYNAMODB_JSON

唯一の落とし穴: S3 エクスポートは CSV を出力しません。 DynamoDB JSON または Amazon Ion のみを、JSON-lines形式(1 行 1 アイテム)の gzip ファイルとして、マニフェストファイルとともに書き出します (AWS ドキュメント: エクスポート出力形式 — データファイルは .json.gz として書かれ、「形式は JSON lines」で、 manifest-summary.json / manifest-files.json とともに)。その後にやはり変換ステップが 必要です。

  • Athena / Glue は、エクスポートされた DynamoDB JSON を直接読みます — S3 プレフィックスに テーブルを向け、SELECT から CSV を書き出します(これが通常の「DynamoDB を S3 に、 それから CSV に」エクスポートするパイプラインです)。AWS は「Athena や AWS Glue など多くの AWS サービスがこの形式を自動的にパースする」と述べています (エクスポート出力形式)。
  • 自前で実装.gz ファイルを展開し、各 JSON 行をパースし、フラット化します (他のすべての方法と同じフラット化問題)。

これはまた テーブル全体 のスナップショットです。一部のアイテムだけをエクスポートする サーバー側フィルタはありません。サブセットが必要なら、後で Athena でフィルタするか、 スクリプト / GUI を使います。

方法 3: 手早いスクリプト(boto3 / Node)

整形された CSV — 特定の列、フィルタされたサブセット、ネストフィールドのカスタム処理 — が 必要なときは、小さなスクリプトが jq との格闘に勝ります。利点は、AWS SDK が型付き JSON を アンマーシャリング してくれることです。boto3 のリソースインターフェースと JS SDK の DynamoDBDocumentClient は、{"price": {"N": "2000"}} ではなく素の {"price": 2000} を 返します(boto3 のリソースインターフェースは「データの型付けを暗黙的にする」、 AWS Python ガイドより。 JS の DocumentClient は「注釈付きのレスポンスデータをネイティブの JavaScript 型に変換する」、 @aws-sdk/lib-dynamodbより)。

import boto3, csv

table = boto3.resource("dynamodb").Table("MyTable")
rows, resp = [], table.scan()
rows += resp["Items"]
while "LastEvaluatedKey" in resp:                  # 最後までページネーション
    resp = table.scan(ExclusiveStartKey=resp["LastEvaluatedKey"])
    rows += resp["Items"]

with open("out.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=["id", "name", "price"])
    w.writeheader()
    for r in rows:
        w.writerow({k: r.get(k) for k in w.fieldnames})

それでも SDK があなたの代わりに決められない 2 つの判断は自分のものです。ネストした マップ / リストをどう フラット化 して列にするか(セルを JSON エンコードする? キーを ドットパスにする?)、そして 疎な 属性をどうするか(ここでは欠けているキーは r.get(k) で空のセルになります)。そして LastEvaluatedKey のループを落とさないこと — 1 回の scan() 呼び出しは最初の 1 MB ページだけを返すので、それがないとテーブルの一部を 黙ってエクスポートしてしまいます。

方法 1 と同じ注意点: ここでのフルテーブル scan もやはり読み取りキャパシティを消費し、 ライブトラフィックと競合します。大きなテーブルには 方法 2 を選び、ダンプを整形してください。

方法 4: DynoTable でのワンクリックエクスポート

スクリプトと CLI のルートは機能しますが、毎回同じフラット化とページネーションのロジックを 作り直すことになります。DynoTable はそれをあなたの代わりにやります。クエリを 実行またはフィルタし、表示中の行をそのまま CSV(または Excel)にエクスポートします — 型記述子は展開され、ネストしたマップとリストはフラット化され、セットは処理され、出力には 実際に欲しいアイテムと列だけが入ります。

現在のビュー をエクスポートするので、 方法 2 のテーブル全体スナップショットでは 得られない、フィルタ / 整形された CSV が — スキャンループを書かずに — 手に入ります。 これはデスクトップの DynamoDB クライアントであり、あなたがすでにテーブルを閲覧するのに 使っているのと同じツールです。他の DynamoDB GUI とどう比較されるかをご覧ください。

落とし穴: DynamoDB JSON とフラットな CSV

どの方法を選んでも、DynamoDB のデータモデルとフラットな CSV の間の同じ一握りの不一致が あなたを噛みます。

  • 型記述子。 生の API / CLI / S3 エクスポートの出力は、すべての値を包みます ({"S": "..."}{"N": "123"})。SDK でアンラップするか、記述子を自分で剥がします。 完全なセットは SNBBOOLNULLMLSSNSBS です — DynamoDB のデータ型を参照してください。
  • ネストしたマップとリストML)は最大 32 レベルの深さ までネストでき (AWS ドキュメント: データ型 — リストとマップは「互いにネストでき、最大 32 レベルの深さの複雑なデータ構造を表現できる」)、 自然な単一列の形がありません。事前に決めましょう: セルを JSON エンコードするか、 ネストしたキーをドットパスの列(address.city)に展開するか。
  • セットSS/NS/BS)は 順序のない コレクションであり、スカラーではありません — AWS は「セット内の値の順序は保持されない」と警告します (データ型)— そのため区切り文字列にフラット化し、要素の順序に依存しないでください。
  • 疎な属性。 DynamoDB はスキーマレスなので、2 つのアイテムが異なる属性を持てます。 固定の列セットはありません。すべてのアイテムにわたってキーを和集合にしないと列がずれます。 これは シングルテーブル設計の直接的な帰結であり、 1 つのテーブルが複数のエンティティ形状を保持します。
  • ページネーション。 Scan(と Query)は 1 回の呼び出しで最大 1 MB を返します。 LastEvaluatedKey でループしないと、最初のページだけを黙ってエクスポートします。 ページネーションを参照してください。
  • 数値の精度。 DynamoDB の数値は最大 38 桁 の精度を持ち、文字列として伝わります (AWS ドキュメント: データ型: 「数値は最大 38 桁の精度を持てる」、「すべての数値は文字列としてネットワーク越しに DynamoDB に送られる」)。スプレッドシートソフトは長い数値や ID を浮動小数点数に 強制変換して桁を失うことがあります。テキストのまま保ってください。

FAQ

AWS CLI で DynamoDB テーブルを CSV にエクスポートするには? テーブルをスキャンし、出力を jq で整形します(方法 1): aws dynamodb scan → 各値の型記述子を剥がす jq@csv。DynamoDB を理解する --output csv はないので、 型剥がしは常に自分で行い、ネストしたマップ、リスト、セットでは壊れます。

AWS から DynamoDB テーブルを直接 CSV にエクスポートできる? 1 ステップではできません。コンソールもマネージド S3 エクスポートも DynamoDB JSON または Amazon Ion を生成し、CSV にはなりません。常に変換ステップが必要です — CLI + jq、 スクリプト、S3 ダンプ上の Athena/Glue、またはフラット化をやってくれる GUI。

本番に影響を与えずに DynamoDB テーブル全体をエクスポートするには? S3 へのエクスポート 機能(方法 2)を使います。非同期で実行され、読み取りキャパシティ ユニットを消費しない ので、ライブトラフィックと競合しません — テーブルのスループットに 課金される Scan と異なり (AWS ドキュメント)。 PITR の有効化が必要で、フィルタされたサブセットではなくテーブル全体をエクスポートします。

DynamoDB を S3 に CSV としてエクスポートするには? マネージドエクスポートは DynamoDB JSON / Ion を S3 に書くだけなので、「CSV に」は 2 ホップ目です。 エクスポートプレフィックスを Athena(または Glue)テーブルとして登録し、SELECT から CSV を書き出します。--export-format CSV はありません。

DynamoDB を Excel にエクスポートするには? まず CSV にエクスポートし(上記いずれかの方法)、その CSV を Excel で開きます — 長い 数値 ID が浮動小数点数に強制されないようテキストのまま保ちます。DynamoDB から直接の .xlsx エクスポートはありません。DynoTable のような GUI は、現在のビューを スプレッドシート対応の CSV として直接保存できます。

エクスポートした JSON に {"S": ...}{"N": ...} があちこちにあるのはなぜ? それは DynamoDB のマーシャリングされたワイヤ形式です — 各値が型記述子でタグ付けされて います。CSV を書く前に、SDK、DynamoDB JSON コンバーター、 または GUI でアンマーシャリングします。データが API、CLI、S3 エクスポートのどこから来ても、 ワイヤ形式は同じです。

自分のテーブルを閲覧、フィルタし、CSV にエクスポートするには DynoTable を、 あるいはまず DynamoDB JSON のサンプルを JSON コンバーターで展開してみてください。

更新日