0

我听说过一些谣言,当主键列中的值发生更改时,应该删除行然后插入新值而不是更新列。

更新主键而不是删除/插入时是否会对性能产生影响?

4

3 回答 3

5

更新主键时:

  • 支持索引已更新。
  • 如果它是外键,将检查孩子。

但是,如果您执行删除和插入操作,则删除两个点都会执行,而插入则更新索引。所以删除和插入没有任何好处。或者我不知道。

简而言之,进行两次操作而不是一次操作会更糟糕。不算删除是最难的操作。

于 2013-09-23T11:39:54.837 回答
3

虽然我坚信您应该设计物理模型以使外键尽可能稳定,但有时您确实需要更新一组键,例如由于重组。

让我们比较一下简单更新和删除+插入主键之间数据方面发生的情况。我们假设您的表被组织为一个堆(默认),并且现在表上没有外键或其他索引:

  1. 简单更新

    • 数据修改:直接在块中修改表的行数据。主键列通常很小,因此不太可能迁移行。主键索引充当常规索引:对键的更新将导致指向旧键的条目被删除,而指向新值的新条目将被插入。
    • 重做条目:更新的重做将包含对数据操作的物理变化:单列更新(小重做)和索引删除+插入。
    • 撤消条目:撤消将包含旧列值(小撤消)和索引的反向插入+删除。

  2. 删除+插入

    • 数据修改(重做):Oracle 将不得不物理删除该行并插入另一行。从直接数据的角度来看,删除行是一个简单的操作:找到包含该行的块,并将该行标记为已删除。如果块仍然包含足够数量的数据(其他未删除的行),它将保持原样。如果不是(低于PCTUSED段的值),它将被添加到符合插入条件的块列表中。由于需要记录所有列的值,因此插入会导致更多的重做。当然,删除旧行并插入新行会导致旧索引条目的删除和新索引条目的创建(同上)。
    • undo entries:删除操作需要记录旧行所有列的值。另一方面,插入在撤消中被保护为简单的删除。

如果表有其他索引,情况会更糟,因为每个索引都需要为删除+插入维护(而主键更新不会触及它们,除非列重叠)。

如果有引用此表的键,则在这两种情况下都会遇到引用问题。如果该表引用其他表,您将再次在删除+插入中进行更多工作(除非引用再次基于主键列,在这种情况下它或多或少相同)。

结论:由于插入+删除会影响基表的所有列,因此它会比简单的更新造成更多的工作:更多的撤消、更多的重做以及对所有索引的两个操作(而不仅仅是主键索引)。

如果您的表是索引组织的,那么工作量将或多或少相同,因为行将被物理移动,但我很确定单个更新仍然比两个单个操作更有效(因为每个操作涉及开销)。

于 2013-09-23T12:32:50.693 回答
1

最大的性能和并发影响是当您在子表 FK 上没有索引时。在这种情况下,Oracle 没有其他选择,只能锁定整个子表并对其进行扫描以验证参照完整性。

也许这不知何故与主键上的 UPDATE 与 DELETE/INSERT 混淆了。可能是因为 Oracle 支持CASCADE ON DELETE但不支持UPDATE.

当您确实需要更新时,请不要使用 delete+insert。

于 2013-09-23T12:26:34.497 回答