入门阅读约 2 分钟

如何在 DynamoDB 中删除多个项

DynamoDB 中没有 DELETE FROM table WHERE …。每一次删除都针对由完整主键标识的一个项——API 没有批量删除操作,没有 truncate,而 DELETE 语句每条也只删除恰好一个项。所以"删除多个项"永远是一个两步的活儿:先找到键,再对每个键发出一次删除,并为了吞吐量打包成批。

本指南涵盖各种批处理选项、全有或全无的事务变体、删光整张表的场景,以及如何在图形界面里用一次选择加两个快捷键做同样的事。

如何在 DynamoDB 中删除多个项?

先收集你想删掉的项的主键(通过 QueryScan),然后分批删除:BatchWriteItem 每次调用最多接受 25 个 DeleteRequestTransactWriteItems 原子地删除最多 100 个项,而 PartiQL 的 DELETE 语句可以用 BatchExecuteStatement 按每批 25 条批量执行。在 DynoTable 里,你选中行并按 ⌘⌫ 暂存这些删除,然后审阅并提交。

第 0 步:收集键

一次删除需要完整的主键——在一张 表上,那就是分区键_和_排序键(AWS:"对于每个主键,你必须提供_所有_的键属性")。你无法按任意属性删除,所以"删除所有 status = 'archived' 的项"要从一次读取开始:

  • 如果条件落在某个键(或某个 GSI 的键)上,一次有针对性的 Query 就能廉价地收集到键。
  • 否则就是一次带筛选的 Scan——不管有没有筛选,它都会读取(并计费)整张表;参见 Query 与 Scan

用一个只返回键属性的 ProjectionExpression,并沿着 LastEvaluatedKey 一路翻到底(分页),否则你会悄无声息地只删掉第一个 1 MB 页里的那部分。

方法 1:BatchWriteItem(每次调用最多 25 个删除)

BatchWriteItem 把最多 25 个 put/delete 请求或 16 MB 打成一次调用(AWS API 参考:"一次 BatchWriteItem 调用最多可通过网络传输 16MB 数据,其中包含最多 25 个项的 put 或 delete 操作")。

aws dynamodb batch-write-item --request-items '{
  "Orders": [
    {"DeleteRequest": {"Key": {"PK": {"S": "ORDER#1001"}, "SK": {"S": "META"}}}},
    {"DeleteRequest": {"Key": {"PK": {"S": "ORDER#1002"}, "SK": {"S": "META"}}}},
    {"DeleteRequest": {"Key": {"PK": {"S": "ORDER#1003"}, "SK": {"S": "META"}}}}
  ]
}'

批处理有三个常绊倒人的性质——全都直接出自 API 参考

  • 它不是原子的。"BatchWriteItem 中指定的各个 PutItemDeleteItem 操作是原子的;但 BatchWriteItem 作为一个整体不是。"有些删除可能落地而另一些没有。
  • **你必须重试 UnprocessedItems。**被限流的请求会以与请求相同的形状出现在响应的 UnprocessedItems 映射中——"通常,你会在一个循环中调用 BatchWriteItem",而且 AWS"强烈建议你在重试之间使用指数退避算法"。
  • 不支持条件。"你不能在单个 put 和 delete 请求上指定条件"——条件删除只能改走 DeleteItem 或事务。一个批次也拒绝在同一次调用里对同一个键执行两个操作。

这个循环的形状——按 25 分块、发送、把剩余的带退避重新排队——与 批量操作 中讲的是同一个。

方法 2:TransactWriteItems(原子删除)

当一组删除必须一起成功或失败时——比如移除一个父项及其 子项——用 TransactWriteItems:最多 100 个动作(删除、put、更新、条件检查)原子地应用,且允许逐项的 。代价是:一次事务写入花费普通写入两倍的写入容量。完整机制(幂等 token、TransactionCanceledException、成本计算)在 DynamoDB 事务

方法 3:PartiQL DELETE,批量执行

PartiQL 并没有解除按键规则——它只是换了个拼法。开发者指南说得很明确(PartiQL DELETE):"一次只能删除一个项。你不能发出一条删除多个项的 DynamoDB PartiQL 语句",而且 WHERE 条件"必须解析为单个主键值"。

要删除多个项,你就批量执行单项语句——BatchExecuteStatement 每批最多运行 25 条语句(全部是读或全部是写,绝不混合):

[
  {"Statement": "DELETE FROM \"Orders\" WHERE PK = 'ORDER#1001' AND SK = 'META'"},
  {"Statement": "DELETE FROM \"Orders\" WHERE PK = 'ORDER#1002' AND SK = 'META'"}
]
aws dynamodb batch-execute-statement --statements file://statements.json

一个没有钉死完整键的 WHERE 会失败——不存在 DELETE FROM Orders WHERE status = 'archived'。更多 PartiQL 模式(及其背后的限制)见 PartiQL 示例PartiQL 与 SQL

删除所有项(truncate)

DynamoDB 没有 truncate。你的选项,按优先顺序:

  1. 删除并重建表。逐项删除整张表要为每个项付一次写入;DeleteTable + CreateTable 则完全绕开了这笔写入账单。代价是:表设置——索引、TTL、、容量模式、标签——不会自己回来;你要在创建时重新声明它们(有基础设施即代码这就不算个事)。
  2. 让项过期。如果你真正想要的是"删除所有早于 X 的东西",TTL 会在后台删除过期项,且不消耗写入容量——一场慢动作的批量删除,分文不花。
  3. Scan + 批量删除方法 1),当表必须保持在线且只删一个子集时——你为扫描到的每个项付一次读取,再为删除的每个项付一次写入。

在 DynoTable 中删除多个项

上面那套先选后删的流程——查询、收集键、分块、重试——正是图形界面应该替你包揽的杂活。在 DynoTable 里它就是一次网格选择:

  1. 运行或筛选一个查询,让你想删掉的行出现在屏幕上。
  2. 选中它们并按 ⌘⌫——每个被选中的行都变成一个暂存删除。此时还没有任何东西碰到 DynamoDB:这些行在网格中染成红色,并作为可审阅的卡片出现在暂存面板中。
  3. 审阅,然后提交。提交以 TransactWriteItems 批次发出,并带乐观锁条件——一个暂存删除只有在该项仍然存在时才会执行——大的暂存批次会自动分块,以保持在 DynamoDB 的事务限制之内。⌘⇧⌫ 跳过审阅,用一个和弦把选择直接删除并提交。
DynoTable 中的暂存删除:选中的行在网格中染成红色,每一行都是提交前暂存面板里一张可审阅的卡片。
DynoTable 中的暂存删除:选中的行在网格中染成红色,每一行都是提交前暂存面板里一张可审阅的卡片。

作用范围是诚实的:你删除的是你选中的行——一次经过审阅、提交前可反悔的操作——而不是一次盲目的全表 truncate。要清空整张表,删掉并重建它(见上文)。

如果某次删除需要手写条件(attribute_exists、版本检查),在 DynamoDB 表达式构建器 中构建精确的 ConditionExpression + 占位符映射,把它挂到一次 DeleteItem 或事务上。

常见问题

能在一次 DynamoDB 调用中删除多个项吗? 能——用 BatchWriteItem 最多 25 个(尽力而为,重试 UnprocessedItems),或用 TransactWriteItems 原子地删除最多 100 个。两者都要求每个项给出完整主键;都不接受用"where"条件来选择项。

DynamoDB 有 DELETE WHERE 吗? 没有。低级 API 和 PartiQL 都无法按条件删除——PartiQL 的 DELETE 要求一个"解析为单个主键值"的 WHERE。你先查询或扫描出键,然后逐个删除。

如何删除一张 DynamoDB 表里的所有项? 要整表清空,删除并重建表——这避免了为每个项付一次写入。要做基于时间的清理,用 TTL,它删除过期项且不消耗写入容量。当表必须保持在线时,Scan + 批量删除是兜底方案。

为什么批量删除之后项又出现了? 几乎总是没有重试的 UnprocessedItems:被限流的 BatchWriteItem 会把失败的删除悄悄放回响应里,而不对它们循环重试的代码会在表里还剩着项的情况下就"完成"了。用指数退避重试,直到那个映射回来是空的。

删除项要花多少钱? 每次删除是一次标准写入(每 1 KB 一个 WCU,事务内翻倍),找键本身也要花读取。用定价计算器估算这笔开销。

想先看清你要删的是什么?下载 DynoTable——选中行,用 ⌘⌫ 暂存删除,审阅差异,确定之后再提交。

更新于