DynamoDB PutItem和UpdateItem有什么区别?

144

根据 DynamoDb 文档,为什么有人会使用 updateItem 而不是 putItem


  • putItem - 将单个项写入表格。如果具有相同主键的项目已存在于表格中,则操作将替换该项目。计算预留吞吐量消耗时,重要的是项目大小较大的那个。
  • updateItem - 修改表格中的单个项。DynamoDB 会考虑更新前后项的大小。消耗的预留吞吐量反映这些项大小中的较大值。即使您只更新了项目属性的子集,updateItem 仍将消耗完整的预留吞吐量 ("before" 和 "after" 项大小中的较大值)。
4个回答

227

两者的主要区别是,PutItem将替换整个项目,而UpdateItem将对其进行更新。

例如:

我有一个项目如下:

userId = 1
Name= ABC
Gender= Male

如果我使用 PutItem 来添加项目

UserId = 1
Country = India

这将替换掉姓名和性别,现在新的条目是用户ID和国家。 如果你想将一个项目从名称=ABC更新到名称=123,你必须使用UpdateItem

您可以使用PutItem来更新它,但需要发送所有参数,而不仅仅是要更新的参数,因为它会用新属性替换该项(在内部删除该项并添加新项)。

希望这样说得通。


感谢Harshal,针对我的使用场景,我总是覆盖每个唯一的(partitionKey+sortKey)所有字段。我想知道是否可以通过使用updateItem来减轻一些性能开销,而不是PutItem。但看起来内部它们的工作方式相同(内部删除项目并添加新项目)。 - Sindhu
6
使用update而非put对性能的影响有什么想法吗? - Amir Karimi
8
@AmirKarimi,简单来说,"Put"将在内部执行3个操作:查找关键字、删除和添加;而"Update"只会执行查找关键字和更新操作,因此我认为"Update"会更快。 - Harshal Bulsara
注意:在上面的示例中,如果我们使用“UserId = 1 Country = India”进行PUT item,则会删除属性“Name = ABC”。就像Harshal Bulsara所提到的那样,它会先删除它,然后添加新项目。 - Juggernaut17
2
当没有找到项目时,您能否运行UpdateItem并插入它? - Freddie
我还没有尝试过那个。从逻辑上讲,那应该不起作用。 - Harshal Bulsara

35

PutItem 覆盖整个项(所有属性)与传递的新版本,而 UpdateItem 仅更新传递的属性。

性能方面: 如果您经常覆盖整个项,PutItem 可能会影响性能,因为它涉及比 UpdateItem 更多的操作,如 FindItem、DeleteOldVersion 和 AddNewVersion。

从成本方面来看,也是不同的:

AWS 根据使用的读/写容量单位计算成本,这些单位完全取决于要覆盖/更新的项目的大小。

PutItem 的情况下,大小将是新旧版本中更大的那一个。例如,用 1 KB 替换一个 2 KB 的项,它将消耗 2 WCUs,但随后的请求只会使用 1 WCU。因此,如果您经常进行覆盖,并且项的大小发生较大变化,将始终计算项的较大版本,并影响成本。

在使用 UpdateItem 修改项目的情况下,大小包括所有项目的现有属性,而不是像 PutItem 那样选择更大的版本 :),但也不仅仅是添加或更新的属性 :(


1
从成本的角度来看,这不是很令人沮丧吗?我想在列表属性上添加一些数据。为什么要消耗整个项目的写入容量呢?有没有解决这种情况的方法?假设我要添加的数据大约50字节,而我的项目大小为200 kb。采取什么正确的方法以最小化WCU? - neiloth
@neiloth 你可能想把这个问题单独提出来问,但通常对于具有频繁追加操作的项目列表,您需要将其作为自己的表格,并将每个追加操作作为put,而不是需要不断更新的单个记录。 - GrandOpener
@GrandOpener 不需要新表,只需要为列表项创建一个专用的pk/sk命名空间的新对象。200kb是巨大的项目。我建议将其拆分成多个项目,除非您确实需要所有读取的内容,并且在写入期间实际上更新了大部分/全部内容。这似乎不是这种情况。 - Lukas Liesis

4
上面答案稍作更正:即使是更新项API也会考虑两个项大小(更新前和更新后)中较大的那一个。请参见文档这里

6
请将此添加为评论。我们不知道您所指的是哪个答案。 - Peter Graham

0
我可能错了,但我认为我们可以这样定义updateItem相对于putItem的唯一好处:
1. 使用putItem时,我们只发送更新后的属性而不是整个项目,因此可以节省网络带宽和传输时间。
2. 在更新属性之前,您不需要“获取”整个项目,因此如果您事先已经知道要更新的内容,而不需要在本地拷贝项目的情况下,您可能可以避免“获取”操作。例如,如果您只是向项目添加一个日期属性,您不需要“获取”整个项目来完成操作,这样您的代码会更简单,并且可以节省读取容量单位来获取项目之前的操作。
3. 如果网络带宽或速度不是问题,并且您已经在本地拥有整个项目,那么仅更新特定属性与整体放入(并覆盖)项目相比,在数据库层面(包括成本)没有任何好处。在Python中,这意味着如果您已经有项目的字典,您只需更改字典并使用putItem将其重新放入表中。因此,如果我已经在本地拥有项目,我从不使用updateItem,因为在成本上没有区别,而且这样的代码更加优雅且易于阅读。
抱歉如果我完全错了,但这是我对文档的理解。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接