Postgresql 当WHERE子句被省略时,Postgres更新要慢得多

Postgresql 当WHERE子句被省略时,Postgres更新要慢得多,postgresql,Postgresql,我正在寻找线索,以理解为什么当WHERE子句上的过滤器被省略时,更新查询变得慢得多 查询的原始版本在负载下运行了200万次,平均每个查询6毫秒: 更新项目 集合名称=$1, 更新了_at=now(), txid=txid_电流(), 版本=版本+1 其中filter1=$2,filter2=$3,version=$4 返回*; 当我取出和version=$4时,相同负载测试下的延迟远更差(236ms): 更新项目 集合名称=$1, 更新了_at=now(), txid=txid_电流(), 版

我正在寻找线索,以理解为什么当
WHERE
子句上的过滤器被省略时,
更新
查询变得慢得多

查询的原始版本在负载下运行了200万次,平均每个查询6毫秒:

更新项目
集合名称=$1,
更新了_at=now(),
txid=txid_电流(),
版本=版本+1
其中filter1=$2,filter2=$3,version=$4
返回*;
当我取出
和version=$4
时,相同负载测试下的延迟更差(236ms):

更新项目
集合名称=$1,
更新了_at=now(),
txid=txid_电流(),
版本=版本+1
其中filter1=$2和filter2=$3
返回*;
filter1+filter2
的元组上有一个唯一的索引,因此它应该始终最多匹配一条记录。PG必须读取整个记录才能生成新的MVCC记录(此查询中还有其他未更新的字段),因此,
version=version+1
的成本应该大致相同

出于与我们的应用程序API设计的其他部分相关的某些原因,我需要从这个查询中删除
version
子句

我应该看什么,以免遭受性能损失


根据@Laurenz Albe的请求,以下是
解释
结果:

with version clause:

UPDATE items
  SET name = $1,
      updated_at = now(),
      txid = txid_current(),
      version = version + 1
  WHERE filter1 = $2 AND filter2 = $3 AND version = $4
  RETURNING *;

Update on items  (cost=0.54..8.58 rows=1 width=637) (actual time=0.553..0.559 rows=1 loops=1)
  Buffers: shared hit=57
  ->  Index Scan using filter1_and_filter2 on items  (cost=0.54..8.58 rows=1 width=637) (actual time=0.064..0.070 rows=1 loops=1)
        Index Cond: (((filter2)::text = 'VBHNTZFLRX1575420065'::text) AND ((filter1)::text = 'UpdateNotifLoadTest'::text))
        Filter: (version = 191)
        Buffers: shared hit=6
Planning time: 0.138 ms
Execution time: 0.609 ms

---------

without version clause:

UPDATE items
  SET name = $1,
      updated_at = now(),
      txid = txid_current(),
      version = version + 1
  WHERE filter1 = $2 AND filter2 = $3
  RETURNING *;

Update on items  (cost=0.54..8.57 rows=1 width=637) (actual time=161.899..161.929 rows=1 loops=1)
  Buffers: shared hit=377
  ->  Index Scan using filter1_and_filter2 on items  (cost=0.54..8.57 rows=1 width=637) (actual time=0.102..0.131 rows=1 loops=1)
        Index Cond: (((filter2)::text = 'RXDJPVBHNT1575419999'::text) AND ((filter1)::text = 'UpdateNotifLoadTest'::text))
        Buffers: shared hit=25
Planning time: 0.140 ms
Execution time: 161.977 ms
奇怪。今天重新运行几次,但无法复制


我以前的方法有一个缺陷。仍然可以繁殖。根据@Bergi的请求,我已经用真实数据更新了活载测试的捕获。

请为这两个查询提供
解释(分析,缓冲)
输出。也许你有一个包含版本的索引?@LaurenzAlbe:我用这些结果编辑了原始问题。在这些问题中,没有附加条款的版本实际上更快?另一方面,您似乎没有传递真实的数据,因为它没有找到要更新的行,这一点很好。我将看看是否可以从负载测试中捕获一个真正的查询并重试。上周原始问题中报告的延迟数(6ms vs 236ms)在今天的负载测试中重复出现。