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=true 或 flag=false(或 flag 为空)的情况执行更新时。但是,这两个语句的结果并不完全等价;或者,至少,它们不是一般的。
有两个主要的副作用:
第一个查询(无 where 子句)将扫描并处理表中的所有行。在第二种情况下,并且具有适当的索引,它可能只处理几行。 “桌面上有什么”(排除触发器的影响)的最终结果将是相同的。实现这一最终结果所花费的时间可能大不相同。
1234563您的第一个查询,并且仅对于行WHERE
的 where 条件 在第二个为 true。同样有两个区别:(1)时间和(2)触发器的动作。例如,如果触发器会更新“lastmod”列,它会在第一种情况下为每一行更新它[这可能不是你想要的]。
...以及可能的第三个:
-
在足够并发的情况下:第一次查询会阻塞表中的所有行;或者该语句可能被阻止更新某些行,因为另一个事务同时是它们。因此,要么等待时间长,要么陷入僵局。更新的行数越多,对争用产生某些影响的可能性就越大......(或死锁等)
最常用的更新方法是使用带有WHERE
子句的查询。一些非常特殊的情况可能会推荐第一个(例如,您实际上希望更新“lastmod”列,即使该行中的其余值没有)。
“默认情况下”使用WHERE
进行查询。某些数据库(即:mysql 和safe update)甚至可能不允许您在没有WHERE
子句的情况下执行更新(或删除)。
【讨论】:
以上是关于Postgres - 没有实际的更新,有副作用吗?的主要内容,如果未能解决你的问题,请参考以下文章
Spring-JPA 可以与 Postgres 分区一起使用吗?