我正在DynamoDB中编写一个简单的日志记录服务。
我有一个日志表,由user_id哈希和时间戳(Unix epoch int)范围键入。
当服务的用户终止他们的帐户时,我……
如果您想在一段时间后删除项目,例如一个月后,只需使用生存时间选项。它会 的 不 强> 计数写入单位。
在您的情况下,我会在日志过期时添加ttl,并在删除用户后保留这些内容。 TTL会确保最终删除日志。
在表上启用生存时间后,后台作业将检查 项目的TTL属性,以查看它们是否已过期。 DynamoDB通常会在48小时内删除过期的项目 过期。项目真正被删除的确切持续时间 到期后特定于工作量的性质和 桌子的大小。已过期但尚未删除的项目将会 仍显示在读取,查询和扫描中。这些物品仍然可以 更新和成功更新以更改或删除过期 属性将被尊重。
在表上启用生存时间后,后台作业将检查 项目的TTL属性,以查看它们是否已过期。
DynamoDB通常会在48小时内删除过期的项目 过期。项目真正被删除的确切持续时间 到期后特定于工作量的性质和 桌子的大小。已过期但尚未删除的项目将会 仍显示在读取,查询和扫描中。这些物品仍然可以 更新和成功更新以更改或删除过期 属性将被尊重。
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html
我们没有截断发电机表的选项。我们必须放弃桌子并重新创建。 DynamoDB费用基于ReadCapacityUnits& WriteCapacityUnits。如果我们使用BatchWriteItem函数删除所有项目,它将使用WriteCapacityUnits.So更好地删除特定记录或删除表格并重新开始。
我理想的做法是调用LogTable.DeleteItem(user_id) - 没有提供范围,并让它为我删除一切。
确实可以理解的要求;我可以想象这些高级操作可能会随着时间的推移而被AWS团队添加(他们有首先从有限的功能集开始并根据客户反馈评估扩展的历史),但这是你应该做的,以避免成本至少完整扫描:
使用 询问 而不是 扫描 检索所有项目 user_id - 无论使用的组合散列/范围主键如何,这都有效,因为 HashKeyValue 和 RangeKeyCondition 是这个API中的单独参数,前者仅针对 复合主键的哈希组件的属性值。 。
user_id
从中继续先前查询的项的主键。一个 如果更早,查询可能会将此值提供为LastEvaluatedKey 查询操作在完成查询之前被中断;或 因为结果集大小或Limit参数。该 LastEvaluatedKey可以在新的查询请求中传回以继续 从那时起的操作。
循环遍历所有返回的项目并且方便 DeleteItem 照常
如突出显示 ivant , BatchWriteItem 手术 让你放 的 或删除 强> 单个API调用中多个表中的多个项目[强调我的] :
要上传一个项目,您可以使用PutItem API并删除一个 item,您可以使用DeleteItem API。但是,当您要上传时 或删除大量数据,例如上传大量数据 来自Amazon Elastic MapReduce(EMR)的数据或从另一个迁移数据 数据库到Amazon DynamoDB,这个API提供了一个高效的 替代。
请注意,这仍有一些相关限制,最值得注意的是:
的 单个请求中的最大操作数 强> - 您最多可以指定25个放置或删除操作;但是,总请求大小不能超过1 MB(HTTP有效负载)。
的 不是原子操作 强> - BatchWriteItem中指定的各个操作是原子的;但BatchWriteItem作为一个整体是“尽力而为”的操作而不是原子操作。也就是说,在BatchWriteItem请求中,某些操作可能会成功,而其他操作可能会失败。 [...]
然而,这显然为像手头的用例提供了潜在的显着收益。
此问题的答案取决于项目数量及其大小和预算。取决于我们有以下3个案例:
1-表中的项目数和项目大小不是很多。然后,Steffen Opel表示你可以使用Query而不是Scan来检索user_id的所有项目,然后遍历所有返回的项目并且 DeleteItem 要么 BatchWriteItem 。但请记住,这里可能会消耗大量的吞吐量。例如,考虑一种情况,您需要从DynamoDB表中删除1000个项目。假设每个项目的大小为1 KB,从而产生大约1 MB的数据。此批量删除任务将需要总共2000个写入容量单位进行查询和删除。要在10秒内执行此数据加载(在某些应用程序中甚至不被视为快速加载),您需要将表的预配置写入吞吐量设置为200个写入容量单位。正如您可以看到它可以使用这种方式,如果它用于较少数量的项目或小尺寸项目。
DeleteItem
BatchWriteItem
2-我们在表格中有很多项目或非常大的项目,我们可以根据时间将它们存储到不同的表格中。然后作为 jonathan说你可以删除表。这要好得多,但我不认为它与你的情况相符。由于您希望删除所有用户数据,无论创建日志的时间是什么,因此在这种情况下您无法删除特定表。如果你想为每个用户都有一个单独的表,那么我想如果用户数量很高那么它的价格如此昂贵,对你的情况来说是不实际的。
3-如果您有大量数据且无法将热数据和冷数据分成不同的表,并且需要经常进行大规模删除,那么不幸的是DynamoDB根本不适合您。它可能会变得更贵或非常慢(取决于您的预算)。在这些情况下,我建议为您的数据找到另一个数据库。
根据DynamoDB文档,您可以删除整个表。
见下文:
“删除整个表比逐个删除项目效率要高得多,这实际上使写入吞吐量翻了一倍,因为你执行的删除操作与put操作一样多”
如果您只想删除数据的一部分,那么您可以为每个月,每年或类似的表单创建单独的表。这样您就可以删除“上个月”并保持其余数据的完整性。
这是使用AWS SDK在Java中删除表的方法:
DeleteTableRequest deleteTableRequest = new DeleteTableRequest() .withTableName(tableName); DeleteTableResult result = client.deleteTable(deleteTableRequest);
我从表中删除所有行的方法i DynamoDb只是使用DynamoDbs ScanAsync将所有行从表中拉出,然后将结果列表提供给DynamoDbs AddDeleteItems。 下面的C#代码对我来说很好。
public async Task DeleteAllReadModelEntitiesInTable() { List<ReadModelEntity> readModels; var conditions = new List<ScanCondition>(); readModels = await _context.ScanAsync<ReadModelEntity>(conditions).GetRemainingAsync(); var batchWork = _context.CreateBatchWrite<ReadModelEntity>(); batchWork.AddDeleteItems(readModels); await batchWork.ExecuteAsync(); }
注意:如果使用YAML / CloudFront创建表,删除表然后从Web控制台再次重新创建表可能会导致问题。