入门阅读约 3 分钟

DynamoDB 基于项的操作

DynamoDB 的 API 分为三大类:基于项的操作,按主键作用于单个项;Query,读取一个分区 内的一段范围;以及 Scan,读取所有内容。本指南讲第一类——你用得最多的四个操作: GetItemPutItemUpdateItemDeleteItem。它们是 DynamoDB 提供的最便宜、最快的调用, 而把它们的区分搞对(尤其是 PutUpdate)能避免一整类意外丢数据的 bug。

什么是 DynamoDB 基于项的操作?

DynamoDB 基于项的操作,是按完整主键作用于单个项的那四个调用:GetItem 读取它,PutItem 创建或完全替换它,UpdateItem 原地修改指定属性,DeleteItem 删除它。每个操作都恰好针对一个项,因而是最快、最便宜的调用——不同于一次读取多项的 Query 和 Scan。

  • GetItem —— 按完整主键读取一个项。
  • PutItem —— 创建或完全替换一个项。
  • UpdateItem —— 创建或原地修改某个项的指定属性
  • DeleteItem —— 按完整主键删除一个项。
  • 这四个都需要完整主键(分区键,若表有排序键还需排序键)—— 它们精确定位到恰好一个项。
  • PutItem 覆盖整个项;UpdateItem 是外科手术式的 —— 把它们搞混,属性就会悄悄消失。

决定性特征:一个项,完整键

每个基于项的操作都按完整主键定位单个项。这正是它们快且便宜的原因 —— DynamoDB 对分区键 做哈希,直奔那个项,完事。没有过滤,没有扫描。如果你不知道完整键,这些就不是合适的工具;那是 Query 和 Scan 的用武之地。

假设你管理以 USER#<id> 为键的用户账户:

PK: USER#204   email, displayName, plan, createdAt
  • USER#204 执行 GetItem → 直接得到那个用户。
  • USER#204 执行 DeleteItem → 删除那个用户。

两者都需要确切的键。没有键,就没有基于项的操作。

PutItemUpdateItem —— 会咬人的那个

这个区分值得牢牢记住:

  • PutItem 写入整个项。 如果 USER#204 已存在,而你用仅含 {email, displayName}PutItem,那么现有的 plancreatedAt 属性就没了 —— put 替换整个项,它不合并。
  • UpdateItem 只改你指定的内容。SET email = …UpdateItem 会保持其他所有属性 不变,并在项不存在时创建它(一次 upsert)。
替换整个项改一部分属性,保留其余修改一个已存在的项?PutItemUpdateItem

经验法则:要修改一个已存在的项就用 UpdateItem,仅当你确实是指「把这个项写成全新的完整 状态」时才用 PutItemPutItemUpdateItem 都接受一个 条件表达式,让你可以让写入有条件地进行(「仅当它尚 不存在时」)。

DynoTable 中的基于项的操作

想看这些操作背后的原始 API 调用吗?在 DynamoDB 表达式构建器中组装表达式和类型化的值映射, 用 DynamoDB JSON 转换器把纯 JSON 项转换成 API 的类型化格式。

在 DynoTable 中,同样的工作变成了可视化:在网格中打开一个项来读取它(一次 GetItem), 编辑属性并提交(一次 UpdateItem),新增或替换一行(一次 PutItem),或者删除一行—— 每次操作一个项。

在 DynoTable 的 Quick View 中读取单个项,附带 Edit Item 和 Copy as JSON 操作。
在 DynoTable 的 Quick View 中读取单个项,附带 Edit Item 和 Copy as JSON 操作。

陷阱与后续步骤

  • PutItem 替换整个项 —— 要在不丢失其余属性的前提下只改几个字段,用 UpdateItem
  • 你必须知道完整主键 —— 没有键就意味着用 Query/Scan,而非基于项的操作。
  • 一次要处理很多项? 别逐个循环调用这些操作 —— 批处理操作能把它们折叠进更少的往返。
  • 需要拿回旧值/新值? 设置 ReturnValues,而不是再补一次 GetItem
  • 相关: Query 与 Scan 讲了读取多项的那一面。

想读、写、删项而一行 API 代码都不写吗?下载 DynoTable,直接操作你的表。

成本:一件物品,一跳

基于项目的读取是 DynamoDB 中最便宜的可寻址访问。 GetItem 开启 2 KB 行消耗 1 最终一致的 RCU(一个 4 KB 块,四舍五入)上)。 Query 返回同一行,因为您知道分区键并且排序键花费相同的容量 - 但如果您只知道分区键并且在应用程序代码中进行过滤,您需要为分区中的每个项目付费。

运营需要钥匙典型用途容量形状
GetItem完整主键按 id 读取的点每件物品 1 块
PutItem完整主键创建或替换整个项目每 KB 1 WCU,四舍五入
UpdateItem完整主键补丁属性书面物品尺寸账单
DeleteItem完整主键删除行与写入商品尺寸相同
Query + 过滤分区(+可选排序条件)一个分区中有许多项目匹配项总和

将代表性项目粘贴到 item-size calculator,然后乘以每秒请求数 pricing calculator 当热路径使用时循环中的 GetItem 与键控良好的 Query

写入的条件表达式

PutItemUpdateItem 都接受可选 condition expressions。典型模式:

  • attribute_not_exists(pk) on put — 仅创建插入,无需竞争。
  • attribute_exists(pk) 更新时 — 拒绝意外创建存根。
  • plan = :old 更新时 — 乐观并发;如果有其他作家则重试先改变计划。

DeleteItem也支持条件——仅当status = :closed时才删除,for 示例。条件不另加单独读取费用; DynamoDB 评估它们在写入尝试期间针对存储的项目。在视觉上构建条件 DynamoDB expression builder;复制 ConditionExpressionExpressionAttributeNamesExpressionAttributeValues 进入您的 SDK 调用。

幂等性和覆盖安全性

没有条件的 PutItem 是整个项目的最后写入者获胜。对于网络钩子处理程序或 SQS 消费者,在已处理的数据上将 put 与 attribute_not_exists 配对标记属性,或使用 UpdateItemSET processed = :true 保护 attribute_not_exists(processed)。当您需要审核日志的先前属性值时,请添加 ⟦5⟧ 放在同一个 UpdateItem 上之前的 GetItem — 一个往返,没有读/写竞争。

选择正确的项目操作

意向致电守卫
按用户 ID 读取个人资料GetItem
如果不存在则创建用户PutItemattribute_not_exists(pk)
更改电子邮件,保留其他字段UpdateItem可选 email <> :old
替换整个配置 blobPutItem仅当有效负载完成时
删除已关闭的票证DeleteItemstatus = :closed
通过已知密钥读取 50 张票BatchGetItem不是 50× GetItem 连续

暂存写入DynoTable

DynoTable 在提交之前在本地暂存 UpdateItemPutItem。你评论属性差异,运行可选的 PartiQL 检查,然后提交 - 映射到上面真正的API调用。批量行删除批量进入 ⟦2⟧ 在引擎盖下重试在未加工的物品上。对于 SDK 代码生成,请在 expression builder 并粘贴发出的处理程序测试旁边的 SDK v3 片段。

更新于