One*_*ofo 38 postgresql performance update postgresql-performance
我有一个与性能相关的问题。假设我有一个名为 Michael 的用户。进行以下查询:
UPDATE users
SET first_name = 'Michael'
WHERE users.id = 123
Run Code Online (Sandbox Code Playgroud)
查询是否会实际执行更新,即使它被更新为相同的值?如果是这样,我该如何防止它发生?
Erw*_*ter 46
由于Postgres的MVCC 模型,并且根据 SQL 的规则,对于子句中没有排除的每一行,都会UPDATE
写入一个新的行版本。WHERE
这确实或多或少地直接或间接地对性能产生了重大影响。“空更新”的每行成本与任何其他更新相同。它们会像任何其他更新一样触发触发器(如果存在),它们必须被WAL 记录,并且它们会产生使表膨胀的死行,并VACUUM
像任何其他更新一样导致更多的工作供以后使用。
索引条目和未更改任何相关列的TOAST列可以保持不变,但对于任何更新的行都是如此。有关的:
排除此类空更新几乎总是一个好主意(当有可能发生时)。您没有在问题中提供表定义。我们必须假设first_name
可以为 NULL(对于“名字”来说这并不奇怪),因此查询必须使用NULL 安全比较:
UPDATE users
SET first_name = 'Michael'
WHERE id = 123
AND first_name IS DISTINCT FROM 'Michael';
Run Code Online (Sandbox Code Playgroud)
如果first_name IS NULL
在更新之前,使用 just 的测试first_name <> 'Michael'
将评估为 NULL,因此从更新中排除该行。偷偷摸摸的错误。如果已定义NOT NULL
列,请使用简单的相等性检查,不过这样会便宜一些。
有关的:
ORM 就像 Ruby on Rail 提供的延迟执行,它将记录标记为已更改(或未更改),然后在需要或调用时将更改提交到数据库。
PostgreSQL 是一个数据库而不是 ORM。如果花时间检查新值是否与查询中的更新值相同,则会降低性能。
因此,无论它是否与新值相同,它都会更新该值。
如果您希望防止这种情况发生,您可以使用 Max Vernon 在他的回答中建议的代码。