我正在编写一个大脚本,里面充满了每天都会运行的更新语句。其中一些更新将影响其他行不会。
我相信不会影响任何事情的更新语句不是很好的做法,但我的问题是:
- 这对性能有多大影响?这与仅在 select 获取某些内容时使用 select 语句和更新有很大不同吗?
谢谢你,蒂亚戈
我正在编写一个大脚本,里面充满了每天都会运行的更新语句。其中一些更新将影响其他行不会。
我相信不会影响任何事情的更新语句不是很好的做法,但我的问题是:
谢谢你,蒂亚戈
首先,SELECT 后跟 UPDATE 在并发下几乎总是不正确的。除非事情在 SERIALIZABLE 隔离级别下运行,否则无法保证SELECT 和 UPDATE之间的行不会更改。
其次,对于有要更新的行的情况, SELECT + UPDATE 的成本根据定义要高于 UPDATE。
最后,在没有行更新的情况下,通过 UPDATE 定位它们的成本通常与通过 SELECT 定位它们的成本相同,因此您没有获得任何收益。我说“经常”,而不是“总是”,因为查询优化器可能会考虑更新与选择的不同策略,并且更新扫描发生在与读取扫描不同的锁定(并发)规则下。
可能有意义的是有一个非常便宜的 SELECT 可以避免昂贵的 UPDATE,即使不是 100% 准确。SELECT 和 UPDATE 之间的条件可能会有很大差异只要你没有得到任何假阴性(SELECT 说不应该有任何行但 UPDATE 会找到行,如果它已经运行)和错误的数量正数很低(SELECT 表示有行,但更精确/更昂贵的 UPDATE 检查实际上并没有找到任何行)。
归根结底,这是一个优化问题,所有优化问题都是从测量开始的。先定位到昂贵的UPDATE,然后开始修改。
这取决于您如何进行更新。如果您使用连接语法进行更新(即)
UPDATE targetTable
FROM targetTable INNER JOIN sourceTable
然后,您可以非常简单地添加 WHERE 子句,仅当您要设置的值实际上不同时才更新该行。
是的,它会影响性能,特别是如果你认为这样的事情......
UPDATE targetTable SET column = column
...将触发在 UPDATE 上定义的触发器。我不是 100% 同意这一点,但我相信这也确实会进入事务日志,因为需要对其进行维护,以便日志尾备份和镜像目标能够完全拼凑事件序列。