分析生产Postgres UPDATE - RETURNING查询速度慢

问题描述 投票:-1回答:1

我们正在运行一个平均有10k活跃用户的Web应用程序,由6个webnode提供服务,并由Postgres 9.4.6提供支持。

我们的监控工具确定了以下缓慢运行的查询,该查询通常具有无法接受的响应时间,在过去几天偶尔会导致中断。

这是一个小表,基本上是内部序列实现(遗留应用程序)跟踪每个其他表的唯一ID:

CREATE TABLE ids_for_records
(
  tableid integer NOT NULL,
  id bigint NOT NULL,
  CONSTRAINT ids_for_records_pk PRIMARY KEY (tableid)
)
WITH (
  OIDS=FALSE
);

该表仅包含约200条记录。我们的webapp节点使用此查询来获取一批专用于自己的ID:

UPDATE ids_for_records
SET id = id + <batchsize>
WHERE tableid = <unique-internal-table-id>
RETURNING id;

我需要找出为什么上述查询的性能在过去几天显着下降:平均约为1秒,但有时也需要30-60秒。在高负载期间,所有节点并行地在多个连接上执行完全相同的查询。

更新:查询由单个(慢)查询持有的锁(来自pg_lock,pg_class和pg_stat_activity)的信息表明,它正在等待来自其他事务的完全相同的查询。因此,我们有同时进行的事务尝试更新(增加ID值)同一行,因此一个活动的所有需要​​的锁会阻塞所有其他的。

数据库是健康的,否则,我们的运营团队在存储,内存或连接方面没有发现任何问题;另一个表的大小最近达到了64GB,但这可能与此有关。

有谁知道什么可能导致这种性能下降?与之前相同的负载,但这个瓶颈查询比以前慢了约5倍。

postgresql database-performance database-sequence
1个回答
0
投票

以下包含一些猜测,请在我猜错的地方纠正我。

查询本身会很快,除非发生一些非常奇怪的事情。需要很长时间的是等待行锁定。

锁在事务的整个持续时间内保持不变,因此可能是与阻塞并发会话的UPDATE语句在同一事务中处理批处理。

解决方案是使用序列。由于您使用一个中心功能以模块化方式构建解决方案,因此解决问题并不困难。

挑战是获得整批序列值。您可以通过使用咨询锁保护setval以安全的方式执行此操作,这可以在事务结束之前释放。请参阅my blog post,了解如何做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.