我有一个可容纳约50M行的表。我想执行一个简单的UPDATE查询:
UPDATE the_table SET flag = true;
对于99%的这些行,该标志已设置为true。因此,只有1%的行必须更改。
我的问题是:Postgres足够聪明,知道这个吗?或者Postgres无论如何都会改变这些99%的行,这将导致典型的过程,如WAL,自动真空,重新索引,与从属同步,......对于整个表,而不仅仅是这些1%的行。
换句话说,以下查询是一种更安全的方法吗?
UPDATE the_table SET flag = true WHERE flag = false;
答案 0 :(得分:4)
不,Postgres不会检查您是否正在更新相同的值。
每隔一段时间就会在邮件列表中讨论这个问题,但大家一致认为支票太贵了,没有必要让所有用户为只有少数用户(通常是坏用户)的东西付费混淆层 - 又名" ORM")需要。
第二种解决方案是进行更新的安全且最佳方式。
答案 1 :(得分:2)
Postgres不会区分 flag = true 或 flag = false (或者 flag为null )的情况执行更新时。但是,这两个陈述的结果并不完全等同;或者,至少,它们不是一般的。
有两个主要的副作用:
第一个查询(无where子句)将扫描并处理表中的所有行。在第二种情况下,并且具有适当的索引,它可能只会去处理几行。最终结果就是“桌上的东西”(除了触发器的影响)将是相同的。实现这一最终结果所需的时间可能大不相同。
如果表(或视图)有trigger触发“ON UPDATE”和“FOR EVERY ROW”(参见CREATE TRIGGER
),则会为每一行调用触发器函数在您的第一个查询的表格上,并且仅针对行WHERE
,其中条件在第二个查询中为真。再两个区别:(1)时间和(2)触发器的动作。例如,如果触发器会更新“lastmod”列,它将为第一种情况下的每一行更新它[可能不是你想要的那样]。
......可能是第三个:
最常用的更新方法是使用带有WHERE
子句的查询。一些非常特殊的情况可能会推荐第一个(例如,你实际上希望更新“lastmod”列,即使行中的其余值不是)。
“默认情况下”使用WHERE
转到查询。某些数据库(即:MySQL和safe update)甚至可能不允许您在没有WHERE
子句的情况下执行UPDATE(或DELETE)。