【问题标题】:Deletion from amazon dynamodb从 amazon dynamodb 中删除
【发布时间】:2013-04-04 12:52:36
【问题描述】:

是否有任何有效的方法可以一次从亚马逊 dynamodb 表中删除所有项目。我已经浏览了 aws 文档,但显示删除了单个项目。

【问题讨论】:

  • 可以直接删除表吗?否则,这可能会有所帮助:stackoverflow.com/questions/9154264/…
  • 感谢 alfredaday!!!!但是每次删除和创建同一个表都会在我的应用程序中产生开销...
  • 另外,表的创建不是即时的。确保在其状态(通过 describeTable 读取)为“ACTIVE”之前不要写入新表
  • 您能详细介绍一下您的用例吗?您的应用程序中需要截断表格的事件是什么?使用您的答案编辑问题,因为它们与您将收到的任何答案相关。
  • 嘿史蒂文!!!!实际上我也在使用 dynamodb 进行测试,所以在运行测试用例 db 后会加载不需要的记录,我需要删除这些记录,以便应用程序可以使用它。因此删除整个表是个坏主意....跨度>

标签: amazon-web-services amazon-dynamodb


【解决方案1】:

执行以下步骤:

  1. 提出删除表请求
  2. 在响应中,您将获得 TableDescription
  3. 使用 TableDescription 再次创建表。

For step 1 and 2 click here

for step 3 click here

这就是我在我的应用程序中所做的。

【讨论】:

  • DeleteTableRequest deleteTableRequest = new DeleteTableRequest() .withTableName("myTable"); DeleteTableResult 结果 = client.deleteTable(deleteTableRequest);
  • 如果表名必须是唯一的,并且删除表请求不是立即的,这将如何工作? AWS 将表置于“删除”状态,实际上需要一段时间才能完成删除。
【解决方案2】:

DynamoDBMapper 只需几行即可完成工作:

AWSCredentials credentials = new PropertiesCredentials(credentialFile);
client = new AmazonDynamoDBClient(credentials);
DynamoDBMapper mapper = new DynamoDBMapper(this.client);
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
PaginatedScanList<LogData> result = mapper.scan(LogData.class,  scanExpression);
for (LogData data : result) {
    mapper.delete(data);
}

【讨论】:

  • scan 相当昂贵;但是使用 query 并不像干净的 API 调用那样
【解决方案3】:

正如 ihtsham 所说,最有效的方法是删除并重新创建表。但是,如果这不切实际(例如,由于表的复杂配置,例如 Lambda 触发器),这里有一些 AWS CLI 命令可以删除所有记录。他们需要 jq 程序来处理 JSON。

逐个删除记录(慢!),假设您的表称为my_table,您的分区键称为partition_key,您的排序键(如果有)称为sort_key

aws dynamodb scan --table-name my_table | \
  jq -c '.Items[] | { partition_key, sort_key }' | \
  tr '\n' '\0' | \
  xargs -0 -n1 -t aws dynamodb delete-item --table-name my_table --key

批量删除记录,最多 25 条记录:

aws dynamodb scan --table-name my_table | \
  jq -c '[.Items | keys[] as $i | { index: $i, value: .[$i]}] | group_by(.index / 25 | floor)[] | { "my_table": [.[].value | { "DeleteRequest": { "Key": { partition_key, sort_key }}}] }' | \
  tr '\n' '\0' | \
  xargs -0 -n1 -t aws dynamodb batch-write-item --request-items

如果您开始看到非空的UnprocessedItems 响应,则说明您的写入容量已超出。您可以通过减少批量大小来解决此问题。对我来说,每个批次大约需要一秒钟的时间来提交,因此每秒写入容量为 5,我将批次大小设置为 5。

【讨论】:

    【解决方案4】:

    仅作记录,在 Python 3 中逐项删除的快速解决方案(使用 Boto3scan()) : (需要设置Credentials。)

    def delete_all_items(table_name):
        # Deletes all items from a DynamoDB table.
        # You need to confirm your intention by pressing Enter.
        import boto3
        client = boto3.client('dynamodb')
        dynamodb = boto3.resource('dynamodb')
        table = dynamodb.Table(table_name)
        response = client.describe_table(TableName=table_name)
        keys = [k['AttributeName'] for k in response['Table']['KeySchema']]
        response = table.scan()
        items = response['Items']
        number_of_items = len(items)
        if number_of_items == 0:  # no items to delete
            print("Table '{}' is empty.".format(table_name))
            return
        print("You are about to delete all ({}) items from table '{}'."
              .format(number_of_items, table_name))
        input("Press Enter to continue...")
        with table.batch_writer() as batch:
            for item in items:
                key_dict = {k: item[k] for k in keys}
                print("Deleting " + str(item) + "...")
                batch.delete_item(Key=key_dict)
    
    delete_all_items("test_table")
    

    显然,这不应该用于具有大量项目的表格。 (100+) 为此,删除/重新创建方法更便宜、更高效。

    【讨论】:

      【解决方案5】:

      如果您无法删除表格,您将需要使用BatchWriteItem。如果您的所有条目都在一个 HashKey 中,您可以使用查询 API 来检索记录,然后一次删除 25 个项目。如果没有,您可能必须扫描。

      或者,您可以为AmazonDynamoDBClient(来自官方 SDK)提供一个简单的包装器,用于收集表中存在的一组哈希/范围键。然后,您无需查询或扫描您在测试后插入的项目,因为您已经构建了 Set。看起来像这样:

      public class KeyCollectingAmazonDynamoDB implements AmazonDynamoDB
      {
          private final AmazonDynamoDB delegate;
          // HashRangePair is something you have to define
          private final Set<Key> contents;
      
          public InsertGatheringAmazonDynamoDB( AmazonDynamoDB delegate )
          {
              this.delegate = delegate;
              this.contents = new HashSet<>();
          }
      
          @Override
          public PutItemResult putItem( PutItemRequest putItemRequest )
                  throws AmazonServiceException, AmazonClientException
          {
              contents.add( extractKey( putItemRequest.getItem() ) );
              return delegate.putItem( putItemRequest );
          }
      
          private Key extractKey( Map<String, AttributeValue> item )
          {
              // TODO Define your hash/range key extraction here
              // Create a Key object
              return new Key( hashKey, rangeKey );
          }
      
          @Override
          public DeleteItemResult deleteItem( DeleteItemRequest deleteItemRequest )
                  throws AmazonServiceException, AmazonClientException
          {
              contents.remove( deleteItemRequest.getKey() );
              return delegate.deleteItem( deleteItemRequest );
          }
      
          @Override
          public BatchWriteItemResult batchWriteItem( BatchWriteItemRequest batchWriteItemRequest )
                  throws AmazonServiceException, AmazonClientException
          {
              // Similar extraction, but in bulk.
              for ( Map.Entry<String, List<WriteRequest>> entry : batchWriteItemRequest.getRequestItems().entrySet() )
              {
                  String tableName = entry.getKey();
                  List<WriteRequest> writeRequests = entry.getValue();
                  for ( WriteRequest writeRequest : writeRequests )
                  {
                      PutRequest putRequest = writeRequest.getPutRequest();
                      if ( putRequest != null )
                      {
                          // Add to Set just like putItem
                      }
                      DeleteRequest deleteRequest = writeRequest.getDeleteRequest();
                      if ( deleteRequest != null )
                      {
                          // Remove from Set just like deleteItem
                      }
                  }
              }
      
              // Write through to DynamoDB
              return delegate.batchWriteItem( batchWriteItemRequest );
          }
      
          // remaining methods elided, since they're direct delegation
      }
      

      KeyDynamoDB SDK 中的一个类,它在构造函数中接受零个、一个或两个AttributeValue 对象来表示哈希键或哈希/范围键。假设它的 equalshashCode 方法有效,您可以在我描述的 Set 中使用。如果他们不这样做,您将不得不编写自己的 Key 类。

      这应该会为您提供一个维护的 Set 以在您的测试中使用。它不是特定于表的,因此如果您使用多个表,则可能需要添加另一层集合。这会将Set&lt;Key&gt; 更改为Map&lt;TableName, Set&lt;Key&gt;&gt;。您需要查看 getTableName() 属性以选择正确的 Set 进行更新。

      测试完成后,获取表格内容并删除应该很简单。

      最后一个建议:使用与应用程序不同的表进行测试。创建一个相同的模式,但给表一个不同的名称。您甚至可能需要不同的 IAM 用户来阻止您的测试代码访问您的生产表。如果您对此有任何疑问,请随时针对该场景提出单独的问题。

      【讨论】:

      • 这种方法可能适用于删除测试数据,但对于真实数据尤其是在扩展时并不理想。这就像在每个 DynamoDB 表上方保留和维护另一个密钥数据存储。
      【解决方案6】:

      您可以使用 AWS Java SDK 重新创建 DynamoDB 表

      // Init DynamoDB client
      AmazonDynamoDB dynamoDB = AmazonDynamoDBClientBuilder.standard().build();
      
      // Get table definition
      TableDescription tableDescription = dynamoDB.describeTable("my-table").getTable();
      
      // Delete table
      dynamoDB.deleteTable("my-table");
      
      // Create table
      CreateTableRequest createTableRequest = new CreateTableRequest()
              .withTableName(tableDescription.getTableName())
              .withAttributeDefinitions(tableDescription.getAttributeDefinitions())
              .withProvisionedThroughput(new ProvisionedThroughput()
                      .withReadCapacityUnits(tableDescription.getProvisionedThroughput().getReadCapacityUnits())
                      .withWriteCapacityUnits(tableDescription.getProvisionedThroughput().getWriteCapacityUnits())
              )
              .withKeySchema(tableDescription.getKeySchema());
      
      dynamoDB.createTable(createTableRequest);
      

      【讨论】:

        【解决方案7】:

        我使用以下 javascript 代码来实现:

        async function truncate(table, keys) {
        
            const limit = (await db.describeTable({
                TableName: table
            }).promise()).Table.ProvisionedThroughput.ReadCapacityUnits;
        
            let total = 0;
            let lastEvaluatedKey = null;
            do {
                const qp = {
                    TableName: table,
                    Limit: limit,
                    ExclusiveStartKey: lastEvaluatedKey,
                    ProjectionExpression: keys.join(' '),
                };
        
                const qr = await ddb.scan(qp).promise();
        
                lastEvaluatedKey = qr.LastEvaluatedKey;
        
                const dp = {
                    RequestItems: {
                    },
                };
        
                dp.RequestItems[table] = [];
        
                if (qr.Items) {
                    for (const i of qr.Items) {
                        const dr = {
                            DeleteRequest: {
                                Key: {
                                }
                            }
                        };
        
                        keys.forEach(k => {
                            dr.DeleteRequest.Key[k] = i[k];
                        });
        
                        dp.RequestItems[table].push(dr);
        
                        if (dp.RequestItems[table].length % 25 == 0) {
                            await ddb.batchWrite(dp).promise();
                            total += dp.RequestItems[table].length;
                            dp.RequestItems[table] = [];
                        }
                    }
                    if (dp.RequestItems[table].length > 0) {
                        await ddb.batchWrite(dp).promise();
                        total += dp.RequestItems[table].length;
                        dp.RequestItems[table] = [];
                    }
                }
        
                console.log(`Deleted ${total}`);
        
                setTimeout(() => {}, 1000);
        
            } while (lastEvaluatedKey);
        }
        
        (async () => {
            truncate('table_name', ['id']);
        })();
        

        【讨论】:

          【解决方案8】:

          在这种情况下,您可以删除表并创建一个新表。

          例子:

          from __future__ import print_function # Python 2/3 compatibility
          import boto3
          
          dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://localhost:8000")
          
          table = dynamodb.Table('Movies')
          
          table.delete()
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-11-03
            • 1970-01-01
            • 1970-01-01
            • 2013-08-20
            • 2015-08-24
            • 1970-01-01
            • 1970-01-01
            • 2022-11-26
            相关资源
            最近更新 更多