如何从DynamoDB中删除大量项目是推荐的方式?
如何从DynamoDB中删除大量项目是推荐的方式?
我正在DynamoDB中编写一个简单的日志记录服务。
我有一个按用户ID哈希和时间戳(Unix epoch int)范围分区键的日志表。
当服务的用户终止他们的帐户时,我需要删除表中的所有项目,无论范围值如何。
如何推荐执行这种操作(请记住可能有数百万个项目需要删除)?
就我能看到,我的选项有:
A:执行扫描操作,在每个返回项目上调用删除,直到没有项目为止
B:执行批处理获取操作,再次在每个项目上调用删除,直到没有项目为止
这两种方法都对我来说看起来很糟糕,因为它们需要很长时间。
我理想情况下想要做的是调用LogTable.DeleteItem(user_id)-而不提供范围,然后让它为我删除所有内容。
根据DynamoDB文档,您只需删除整个表即可。如下所示:
“删除整个表比逐个删除项目更高效,因为您执行的删除操作数量等于放入操作,从而将写入吞吐量翻倍。”
如果您只想删除数据子集,则可以为每个月、每年或类似的项制作单独的表。这样,您可以删除“上个月”,并保留其余数据完好无损。
以下是使用AWS SDK在Java中删除表的方法:
DeleteTableRequest deleteTableRequest = new DeleteTableRequest() .withTableName(tableName); DeleteTableResult result = client.deleteTable(deleteTableRequest);
我的理想情况是调用LogTable.DeleteItem(user_id)时不必提供范围参数,它能够自动删除所有内容。
这是一个可以理解的请求,我可以想象AWS团队可能随着时间推移会增加这样的高级操作(他们有一个历史,首先从有限的功能集开始并根据客户反馈评估扩展),但是至少可以避免全面扫描的成本,以下是您应该做的:
-
使用查询而不是扫描来检索所有
user_id
的项目 - 这适用于使用组合哈希/范围主键的情况,因为HashKeyValue和RangeKeyCondition在此API中是单独的参数,并且前者仅针对复合主键的哈希组件的属性值..- 请注意,您通常需要处理查询API分页,参见ExclusiveStartKey参数:
从其中继续较早查询的项的主键。如果查询操作由于结果集大小或Limit参数而中断,则较早的查询可能将此值作为LastEvaluatedKey提供。 LastEvaluatedKey可以在新的查询请求中传递回来以从该点继续操作。
- 请注意,您通常需要处理查询API分页,参见ExclusiveStartKey参数:
-
循环遍历所有返回的项目,并像通常一样使用DeleteItem
- 更新:像这种用例最适用的方法可能是BatchWriteItem(有关详细信息,请参见下文)。
更新
正如ivant所提出的,BatchWriteItem操作可以使您在单个API调用中放置或删除多个表中的多个项目 [我的强调]:
要上传一个项目,您可以使用PutItem API,要删除一个项目,可以使用DeleteItem API。但是,当您要上传或删除大量数据时,例如从Amazon Elastic MapReduce(EMR)上传大量数据或将数据从另一个数据库迁移到Amazon DynamoDB中,此API提供了一种有效的替代方法。
请注意,这仍然有一些相关的限制,尤其是:
-
单个请求中的最大操作数 - 您可以指定最多25个put或delete操作; 但是,总请求大小不能超过1 MB (HTTP负载)。
-
不是原子操作 - 在BatchWriteItem中指定的单个操作是原子的; 但整个BatchWriteItem是一种"尽力而为"的操作,而不是原子操作。也就是说,在BatchWriteItem请求中,某些操作可能成功,而其他操作可能失败。[...]
尽管如此,这显然对像这样的用例产生了潜在的显著收益。