如何更新 DynamoDB 表中的属性,而不考虑键或条件?



我有一个 DynamoDB 表说data.此表有 400k 个项目。每个项目有 4 个字段 -

  • ID(字符串)这是我的分区键
  • 状态(是/否)
  • date_added

现在所有项目都有一个status= "Y"。如何更新所有项目并将所有 400k 项目的状态设置为"N",而不考虑键或任何条件?

在 MySQL 中,等效的语句是 -

UPDATE data SET status = 'N';

我希望通过命令行或最好使用 boto3 在 python 中做到这一点

没有简单或便宜的方法可以做你想做的事情。您基本上需要做的是读取写入整个数据库:

  1. 如果您知道单个项目的键,则可以执行UpdateExpression"set status = :N"UpdateItem请求。这只会修改"status"属性(其余部分保持不变),但你将产生的成本(或你将使用的预置吞吐量)将是写入整个项目的成本。因此,所有这些操作的总和将是重写整个数据库的成本。
  2. 您应该在上述UpdateItem中添加一个ConditionExpression,该仅在项目实际仍然存在时才更新项目(您可以在其 key 属性上使用attribute_exists()条件来验证项目是否存在)。这将允许工作负载在执行这些更改时删除项目。
  3. 在开始此更改过程之前,请更改客户端代码以编写状态 = N 的新项。更改过程可能会错过这些新项目,但如果它们已创建时状态 = N,则没关系。
  4. 您不能使用BatchWriteItems(boto3 中的batch_writer())一起修改一组项目,因为此批处理操作只能替换项目,而不能修改现有项目的属性。在任何情况下,BatchWriteItems都不会降低成本(批处理的成本与它们包含的请求相同)。

阅读

  1. 要获取数据库中所有现有键的列表,要执行上述读取,您需要使用Scan操作,将Projection设置为KEYS_ONLY以仅获取键(您不需要数据)。不幸的是,您的成本将与阅读整个项目相同,而不仅仅是阅读密钥。因此,所有这些扫描操作的成本总和将是读取整个数据库。

如果您为此表使用预置容量,则可以使用客户端请求未使用的任何多余容量在后台缓慢地执行此更改,基本上是"免费"。

这在您的情况下是否有意义实际上取决于您预置了多少多余容量(读取和写入!如果这样做,则需要注意不要为此后台操作使用太多容量并伤害真实用户 - 您需要某种控制器来注意到容量超出的错误并减少后台进程使用的容量。

如果您实际上已经支付了大量多余的预置容量,则可以根据需要尽快执行此后台操作!读取部分,Scan,可以根据需要快速并行完成(使用"并行扫描"功能),而不同密钥的写入部分显然也可以并行完成。

以下代码使用 DynamoDB APIbatch_write_item批量更新大小为 25 的项目,这是batch_write_item在单个 API 调用中可以接受的最大项目数。如果您的项目很大,您可能需要调整此数字。

警告:这只是一个概念验证示例。您应自行承担使用风险。

import boto3
def update_status(item):
item['status'] = {
'S': 'N'
}
return item
client = boto3.client('dynamodb', region_name='<ddb-region>')
paginator = client.get_paginator('scan')
operation_parameters = {
'TableName': '<ddb-table-name>',
'PaginationConfig': {
'PageSize': 25
}
}
page_iterator = paginator.paginate(**operation_parameters)
for page in page_iterator:
response = client.batch_write_item(RequestItems={
'<ddb-table-name>': [
{
'PutRequest': {
'Item': update_status(item)
}
}
for item in page['Items']
]
})
print(response)

最新更新