从DynamoDB导出数据

64

是否可以以某种格式从DynamoDB表中导出数据?

具体的用例是,我想要从生产DynamoDB数据库中导出数据,并将这些数据导入我的本地DynamoDB实例,以便我的应用程序可以使用本地数据副本而不是生产数据。

我使用标准的DynamoDB-local作为本地DynamoDB实例。

21个回答

68

这将把所有项目导出为JSON文档

aws dynamodb scan --table-name TABLE_NAME > export.json

这个脚本将从远程 DynamoDB 表中读取,并导入到本地完整表中。

TABLE=YOURTABLE
maxItems=25
index=0

DATA=$(aws dynamodb scan --table-name $TABLE --max-items $maxItems)
((index+=1)) 
echo $DATA | jq ".Items | {\"$TABLE\": [{\"PutRequest\": { \"Item\": .[]}}]}" > inserts.jsons
aws dynamodb batch-write-item --request-items file://inserts.jsons --endpoint-url http://localhost:8000


nextToken=$(echo $DATA | jq '.NextToken')
while [[ "${nextToken}" != "" ]]
do
  DATA=$(aws dynamodb scan --table-name $TABLE --max-items $maxItems --starting-token $nextToken)
  ((index+=1))
  echo $DATA | jq ".Items | {\"$TABLE\": [{\"PutRequest\": { \"Item\": .[]}}]}" > inserts.jsons
  aws dynamodb batch-write-item --request-items file://inserts.jsons --endpoint-url http://localhost:8000
  nextToken=$(echo $DATA | jq '.NextToken')
done

这里是使用文件将导出的数据保存到磁盘上的脚本版本。

TABLE=YOURTABLE
maxItems=25
index=0
DATA=$(aws dynamodb scan --table-name $TABLE --max-items $maxItems)
((index+=1))
echo $DATA | cat > "$TABLE-$index.json"

nextToken=$(echo $DATA | jq '.NextToken')
while [[ "${nextToken}" != "" ]]
do
  DATA=$(aws dynamodb scan --table-name $TABLE --max-items $maxItems --starting-token $nextToken)
  ((index+=1))
  echo $DATA | cat > "$TABLE-$index.json"
  nextToken=$(echo $DATA | jq '.NextToken')
done

for x in `ls *$TABLE*.json`; do
  cat $x | jq ".Items | {\"$TABLE\": [{\"PutRequest\": { \"Item\": .[]}}]}" > inserts.jsons
  aws dynamodb batch-write-item --request-items file://inserts.jsons --endpoint-url http://localhost:8000
done

如果您选择“文本”选项并勾选“DynamoDB Json”,则可以在AWS控制台中使用此格式逐个创建项目。 - Aposhian
警告:如果 DynamoDB 包含转义字符(例如换行符),则在某些 shell 中可能无法正常工作。 - Woodz
1
@IvailoBardarov 不幸的是,bash(以及像echo这样的bash内置工具-请参见https://dev59.com/mGoy5IYBdhLWcg3wkO2g#GKCdEYcBWogLw_1bdNd_)的行为在不同的操作系统上不一致。在Intel MacOS 11.1上,使用包含转义换行符(\n)的DynamoDB记录时,此脚本将转义换行符替换为JSON文件中的实际换行符,从而破坏了带有以下内容的jq调用: parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 2, column 23。我使用sed来双重转义\n解决了这个问题。 - Woodz
如果有人使用AWS SQL WORKBENCH,重要的是要使用region=localhost设置batch-write-item命令,并为正确的凭据设置环境变量 - 否则您将无法看到已导入的数据...另一个选择是在启动本地dynamo时使用-SharedDb标志 - 这可以节省所有这些配置。 - Yitzchak
@Woodz将echo $DATA替换为printf "%s" $DATA有帮助吗? - Ivailo Bardarov
显示剩余2条评论

20

有一款名为DynamoDBtoCSV的工具可以用于将所有数据导出到CSV文件。但是,如果要进行另外一种操作,则需要自己构建工具。我的建议是将此功能添加到工具中,并将其贡献给Git存储库。


另一种方法是使用AWS数据管道完成此任务(您将节省从AWS基础架构外读取数据的所有费用)。 这种方法类似于:

  1. 构建输出管道
  2. 下载文件。
  3. 使用自定义读取器解析它。

1
有趣的解决方案,很想看看那个“自定义读取器”,因为数据类型有很多噪音。 - Vadorequest
您还可以查看此模板以创建和激活管道。 https://usecases.totalcloud.io/use-cases/aws-dynamodb-to-s3-exporter https://usecases.totalcloud.io/use-cases/activate-dynamodb-export-pipeline - Veer Abheek Singh Manhas
我想为这篇帖子提供一个运行示例的编辑建议,但被版主拒绝了,感谢版主。无论如何,以下是运行DynamoDbToCsv脚本的方法。 sudo npm install -g dynamodbexportcsv; DynamoDbExportCsv --table "yourtable" --awsregion "us-east-1" --columns "col1,col2,col3" --scans 8 --gzip; cat *.gz > combined.csv.gz - Colin D

19
这里有一种使用aws clijq从表中导出某些数据的方法(通常我们只想在本地获取生产数据的样本)。假设我们有一个名为my-prod-table的生产表和一个名为my-local-table的本地表。
要导出数据,请运行以下命令:
aws dynamodb scan --table-name my-prod-table \
| jq '{"my-local-table": [.Items[] | {PutRequest: {Item: .}}]}' > data.json

基本上发生的情况是我们扫描我们的prod表,将扫描的输出转换成batchWriteItem的格式,并将结果转储到文件中。
要导入本地表中的数据,请运行:
aws dynamodb batch-write-item \
--request-items file://data.json \
--endpoint-url http://localhost:8000

注意:使用batch-write-item请求时有一些限制 - BatchWriteItem操作最多可以包含25个单独的PutItem和DeleteItem请求,并且可以写入高达16 MB的数据(每个单独项的最大大小为400 KB)。


2
这行代码在Windows中应该是什么样子? - Žilvinas

13

将其从DynamoDB界面导出到S3。

然后使用sed将其转换为Json:

sed -e 's/$/}/' -e $'s/\x02/,"/g' -e $'s/\x03/":/g' -e 's/^/{"/' <exported_table> > <exported_table>.json

源代码


5
我扩展了Valy dia的解决方案,仅使用aws-cli | jq即可完成全部导出过程。
aws dynamodb scan --max-items 25 --table-name <TABLE_NAME> \
| jq '{"<TABLE_NAME>": [.Items[] | {PutRequest: {Item: .}}]}' > data.json

aws dynamodb describe-table --table-name <TABLE_NAME> > describe.json | jq ' .Table | {"TableName": .TableName, "KeySchema": .KeySchema, "AttributeDefinitions": .AttributeDefinitions,  "ProvisionedThroughput": {
      "ReadCapacityUnits": 5,
      "WriteCapacityUnits": 5
}}' > table-definition.json

aws dynamodb create-table --cli-input-json file://table-definition.json  --endpoint-url http://localhost:8000 --region us-east-1

aws dynamodb batch-write-item --request-items file://data.json --endpoint-url http://localhost:8000

aws dynamodb scan --table-name <TABLE_NAME> --endpoint-url http://localhost:8000

Windows版本 aws dynamodb describe-table --no-verify-ssl --table-name <TABLE> | jq ".Table | {"TableName": .TableName, "KeySchema": .KeySchema, "AttributeDefinitions": .AttributeDefinitions, "ProvisionedThroughput": { "ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, "GlobalSecondaryIndexes": {"IndexName": .IndexName, "KeySchema": .KeySchema, "Projection": .Projection, "ProvisionedThroughput": { "ReadCapacityUnits": 5, "WriteCapacityUnits": 5 }}}" - Sólon Soares
为了让第二行代码工作,您必须省略“> describe.json”部分。 - Yitzchak

3

我认为我的回答更接近Ivailo Bardarov的想法,如果计划从Linux实例运行此操作,请执行以下步骤:

1.登录AWS账户并转到IAM创建一个具有受限策略的用户角色(出于安全考虑)。这应该仅限于读取您希望备份的DynamoDB表。

2.复制访问密钥和秘密密钥,并更新下面的Linux命令(但请确保您的表不是很大,可能会在运行此命令的计算机上创建空间问题)。

AWS_ACCESS_KEY_ID='put_your_key' AWS_SECRET_ACCESS_KEY='put_your_secret' aws --region='put_your_region' dynamodb scan --table-name 'your_table_name'>> export_$(date "+%F-%T").json

注意类似的命令也可以在Windows/Powershell上执行,我没有测试过,因此不在这里添加。


1
我在Windows上进行了测试,这是一个样例:aws dynamodb scan --table-name=TableA > export.json --region=us-east-1 - influent
感谢您的确认。 - grepit

3
我发现目前最好的用于简单导入/导出(包括通过 DynamoDB Local 进行往返)的工具是这个 Python 脚本:

https://github.com/bchew/dynamodump

这个脚本支持模式导出/导入以及数据导入/导出。它还使用批量API进行高效操作。
我已经成功地使用它将数据从DynamoDB表中取出,用于DynamoDB本地开发,对我的需求来说效果非常好。

2

试用我的简单 node.js 脚本 dynamo-archive。它以 JSON 格式导出和导入。


1
它基本上是坏的 - 它可以导出但无法导入,它只会崩溃。 - Denis Mysenko
@DenisMysenko,请提交一个工单,我们会进行修复。 - yegor256

2

@Ivailo Bardarov 的回答基础上,我编写了以下脚本,将远程 DynamoDB 中的重复表复制到本地:

#!/bin/bash
declare -a arr=("table1" "table2" "table3" "table4")
for i in "${arr[@]}"
do
    TABLE=$i
    maxItems=25
    index=0
    echo "Getting table description of $TABLE from remote database..."
    aws dynamodb describe-table --table-name $TABLE > table-description.json
    echo
    echo "Creating table $TABLE in the local database..."
    ATTRIBUTE_DEFINITIONS=$(jq .Table.AttributeDefinitions table-description.json)
    KEY_SCHEMA=$(jq .Table.KeySchema table-description.json)
    BILLING_MODE=$(jq .Table.BillingModeSummary.BillingMode table-description.json)
    READ_CAPACITY_UNITS=$(jq .Table.ProvisionedThroughput.ReadCapacityUnits table-description.json)
    WRITE_CAPACITY_UNITS=$(jq .Table.ProvisionedThroughput.WriteCapacityUnits table-description.json)
    TABLE_DEFINITION=""

    if [[ "$READ_CAPACITY_UNITS" > 0 && "$WRITE_CAPACITY_UNITS" > 0 ]]
    then
    TABLE_DEFINITION="{\"AttributeDefinitions\":$ATTRIBUTE_DEFINITIONS,\"TableName\":\"$TABLE\",\"KeySchema\":$KEY_SCHEMA,\"ProvisionedThroughput\":{\"ReadCapacityUnits\":$READ_CAPACITY_UNITS,\"WriteCapacityUnits\":$WRITE_CAPACITY_UNITS}}"
    else
    TABLE_DEFINITION="{\"AttributeDefinitions\":$ATTRIBUTE_DEFINITIONS,\"TableName\":\"$TABLE\",\"KeySchema\":$KEY_SCHEMA,\"BillingMode\":$BILLING_MODE}"
    fi

    echo $TABLE_DEFINITION > create-table.json
    aws dynamodb create-table --cli-input-json file://create-table.json --endpoint-url http://localhost:8000
    echo "Querying table $TABLE from remote..."
    DATA=$(aws dynamodb scan --table-name $TABLE --max-items $maxItems)
    ((index+=1))
    echo "Saving remote table [$TABLE] contents to inserts.json file..."
    echo $DATA | jq ".Items | {\"$TABLE\": [{\"PutRequest\": { \"Item\": .[]}}]}" > inserts.json
    echo "Inserting rows to $TABLE in local database..."
    aws dynamodb batch-write-item --request-items file://inserts.json --endpoint-url http://localhost:8000

    nextToken=$(echo $DATA | jq '.NextToken')        
    while [[ "$nextToken" != "" && "$nextToken" != "null" ]]
    do
      echo "Querying table $TABLE from remote..."
      DATA=$(aws dynamodb scan --table-name $TABLE --max-items $maxItems --starting-token $nextToken)
      ((index+=1))
      echo "Saving remote table [$TABLE] contents to inserts.json file..."
      echo $DATA | jq ".Items | {\"$TABLE\": [{\"PutRequest\": { \"Item\": .[]}}]}" > inserts.json
      echo "Inserting rows to $TABLE in local database..."
      aws dynamodb batch-write-item --request-items file://inserts.json --endpoint-url http://localhost:8000
      nextToken=$(echo "$DATA" | jq '.NextToken')
    done
done

echo "Deleting temporary files..."
rm -f table-description.json
rm -f create-table.json
rm -f inserts.json

echo "Database sync complete!"

这个脚本循环遍历字符串数组,对于每个表名,它首先获取表的描述并使用最少量的必要参数构建创建JSON文件并创建表。然后,它使用@Ivailo Bardarov提供的逻辑来生成插入语句并将它们推到已创建的表中。最后,它清理生成的JSON文件。
请注意,我的目的只是为了为开发目的创建粗略的表副本(因此使用了最少量的必要参数)。

1

对于那些更喜欢使用Java的人,可以使用DynamodbToCSV4j

JSONObject config = new JSONObject();
config.put("accessKeyId","REPLACE");
config.put("secretAccessKey","REPLACE");
config.put("region","eu-west-1");
config.put("tableName","testtable");
d2csv d = new d2csv(config);

运行得非常好。但是,这个库需要实现最后评估键的分页功能。 - ZZzzZZzz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接