Postgres - 没有实际的更新,有副作用吗?

时间:2017-03-16 07:59:27

标签: performance postgresql query-performance

我有一个可容纳约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;

2 个答案:

答案 0 :(得分:4)

不,Postgres不会检查您是否正在更新相同的值。

每隔一段时间就会在邮件列表中讨论这个问题,但大家一致认为支票太贵了,没有必要让所有用户为只有少数用户(通常是坏用户)的东西付费混淆层 - 又名" ORM")需要。

第二种解决方案是进行更新的安全且最佳方式。

答案 1 :(得分:2)

Postgres不会区分 flag = true flag = false (或者 flag为null )的情况执行更新时。但是,这两个陈述的结果并不完全等同;或者,至少,它们不是一般的。

有两个主要的副作用:

  1. 第一个查询(无where子句)将扫描并处理表中的所有行。在第二种情况下,并且具有适当的索引,它可能只会去处理几行。最终结果就是“桌上的东西”(除了触发器的影响)将是相同的。实现这一最终结果所需的时间可能大不相同。

  2. 如果表(或视图)有trigger触发“ON UPDATE”和“FOR EVERY ROW”(参见CREATE TRIGGER),则会为每一行调用触发器函数在您的第一个查询的表格上,并且仅针对行WHERE ,其中条件在第二个查询中为真。再两个区别:(1)时间和(2)触发器的动作。例如,如果触发器会更新“lastmod”列,它将为第一种情况下的每一行更新它[可能不是你想要的那样]。

  3. ......可能是第三个:

    1. 在充分并发的场景中:第一个查询将阻止表中的所有行;或者语句可能会被阻止更新某些行,因为另一个事务同时是它们。所以,要么是漫长的等待时间,要么是死锁。更新的行数越多,对争用产生影响的可能性就越高......(或死锁等)
    2. 最常用的更新方法是使用带有WHERE子句的查询。一些非常特殊的情况可能会推荐第一个(例如,你实际上希望更新“lastmod”列,即使行中的其余值不是)。

      “默认情况下”使用WHERE转到查询。某些数据库(即:MySQL和safe update)甚至可能不允许您在没有WHERE子句的情况下执行UPDATE(或DELETE)。