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

Posted

技术标签:

【中文标题】Postgres - 没有实际的更新,有副作用吗?【英文标题】:Postgres - No actual UPDATE, has it side-effects? 【发布时间】:2017-03-16 07:59:26 【问题描述】:

我有一个包含大约 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;

【问题讨论】:

它将更新尽可能多的行。在您没有where 的情况下,它将更新所有行,因此请务必使用第二条语句 强制使用where子句,否则会影响所有行。 【参考方案1】:

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

在邮件列表中时不时地讨论这个问题,但一致认为支票太贵了,让所有用户为只有少数用户(通常是差的用户)支付的东西没有意义混淆层 - 又名“ORM”)需要。

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

【讨论】:

混淆层 - 又名“ORM”;) @klin:ORM 不代表“模糊关系模型”吗? :) 我想是的,尤其是当我看到诸如如何在我的 ORM 中编写此查询? 之类的问题时【参考方案2】:

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

有两个主要的副作用:

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

    1234563您的第一个查询,并且仅对于行 WHEREwhere 条件 在第二个为 true。同样有两个区别:(1)时间和(2)触发器的动作。例如,如果触发器会更新“lastmod”列,它会在第一种情况下为每一行更新它[这可能不是你想要的]。

...以及可能的第三个:

    在足够并发的情况下:第一次查询会阻塞表中的所有行;或者该语句可能被阻止更新某些行,因为另一个事务同时是它们。因此,要么等待时间长,要么陷入僵局。更新的行数越多,对争用产生某些影响的可能性就越大......(或死锁等)

最常用的更新方法是使用带有WHERE 子句的查询。一些非常特殊的情况可能会推荐第一个(例如,您实际上希望更新“lastmod”列,即使该行中的其余值没有)。

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

【讨论】:

以上是关于Postgres - 没有实际的更新,有副作用吗?的主要内容,如果未能解决你的问题,请参考以下文章

Debezium 心跳表未更新

Spring-JPA 可以与 Postgres 分区一起使用吗?

没有可序列化事务的 Postgres 序列化错误

Postgres 物化视图或 CREATE TABLE AS 如果不增量更新?

更新的Xubuntu,Postgres停止工作

使用 node-postgres 更新数据的更简单方法?