2017-03-16 37 views
3

我有一张桌子可容纳大约50M行。我想执行一个简单的UPDATE查询:Postgres - 没有实际的更新,是否有副作用?

UPDATE the_table SET flag = true; 

对于这些行的99%,该标志已被设置为true。所以只有1%的行必须改变。

我的问题是:是Postgres足够聪明知道这一点?或者Postgres会改变这些99%的行,这将导致典型的过程,比如WAL,自动真空,重新索引,同步到奴隶......,对于整个表而言,而不仅仅是这些1%的行。

换句话说,下面的查询是否更安全?

UPDATE the_table SET flag = true WHERE flag = false; 
+0

它将更新所告知的行数。在你没有'where'的情况下它会更新所有的行,所以肯定要去第二条语句 –

+0

必须使用where子句,否则所有的行都会受到影响。 – klin

回答

2

Postgres将不是这种情况之间进行区分。但是,这两种说法的结果并不完全相同;或者至少它们并不普遍。

主要有两大副作用:

  1. 第一个查询(没有WHERE子句)将扫描和处理表中的所有行。在第二种情况下,并且有适当的索引,它可能只会处理几行。就“桌面上的事物”(禁止触发器的效果)而言,最终的结果将是相同的。实现这一最终结果所需的时间可能会有很大差异。

  2. 如果表(或视图)具有trigger是火灾“ON UPDATE”和“每一行”(见CREATE TRIGGER),则触发功能将被要求对表中的每一行与你的第一个查询,仅在行WHERE其中条件在第二个上为真。再次有两点不同:(1)时间和(2)触发器的动作。例如,如果触发器会更新“lastmod”列,则会在第一种情况下更新它的每一行[这可能不是您想要的]。

...和可能的第三之一:

  • 在足够并行情形:所述第一查询将阻止在表中的所有行;或者该语句可能因更新某些行而被阻止,因为另一个事务是同时发生的。所以,无论是漫长的等待时间还是僵局。更新的行数越高,对竞争产生影响的可能性就越高......(或死锁等)
  • 最常用的更新方式是使用带有WHERE子句的查询。一些非常特殊的情况可能会推荐第一种情况(例如,即使该行中其余的值没有更新,您也会更新“lastmod”列)。

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

    4

    不,Postgres不检查您是否更新到相同的值。

    不时地在邮件列表上讨论这个问题,但共识是检查过于昂贵,没有意义让所有用户都支付一些只有少数用户(通常是用户糟糕的混淆层 - 又名“ORM”)需要。

    第二种解决方案是进行更新的安全和最佳方式。其中标志=真标志=假(或标志为空,就此而言)执行更新时

    +0

    混淆图层 - 又名“ORM”;) – klin

    +1

    @klin:不是ORM代表“混淆关系模型”? :) –

    +2

    我这么认为,特别是当我看到如下问题时*我如何在我的ORM中编写这个查询?* – klin

    相关问题