使用 pg_stat_activity 中的 'active' 个进程测量 Postgres 中每个数据库的负载?

Measuring load per database in Postgres using 'active' processes in pg_stat_activity?

我正在尝试测量同一个 Postgres 服务器上的各种数据库所产生的负载,以确定如何最好地将它们拆分到多个服务器上。我设计了这个查询:

select
 now() as now,
 datname as database,
 usename as user,
 count(*) as processes
from pg_stat_activity
where state = 'active'
 and waiting = 'f'
 and query not like '%from pg_stat_activity%'
group by
 datname,
 usename;

但是活动进程少得惊人!

深入挖掘我 运行 一个简单的查询 returns 20k 行并用了 5 秒完成,据我 运行 的客户说。我那段时间查询pg_stat_activity的时候,进程是idle!这个实验我重复了几次。

Postgres 文档说 active 意味着

The backend is executing a query.

空闲意味着

The backend is waiting for a new client command.

真的比这更微妙吗?为什么我签入时进程 运行 我的查询未 活动

如果这种方法有缺陷,除了定期对活动进程的数量进行抽样之外,还有什么替代方法可以测量数据库的负载 g运行粒度?

您对activeidleidle in transaction的期望非常正确。我能想到的唯一解释是显示数据客户端的巨大延迟。所以查询确实在服务器上完成,会话是 idle,但您看不到客户端的结果。

关于负载测量 - 我不会太依赖活动会话的数量。在活动状态下命中快速查询纯属运气。例如,假设您可以每秒检查 pg_stat_activity 并查看一个活动会话,但在测量之间,一个数据库被查询了 10 次,另一个数据库被查询了一次 - 然而这些数字中的 none 将被看到。因为他们在处决之间很活跃。而这 10+1 个活动状态(虽然意味着一个数据库的查询频率是 10 倍)并不意味着你应该考虑负载——因为集群没有加载太多,你甚至无法捕获执行。但这不可避免地意味着您可以捕获许多活动会话,但这并不意味着服务器确实已加载。

所以至少将 now()-query_start 用于您的查询以捕获更长的查询。或者甚至更好地节省一些经常查询的执行时间,并衡量它是否会随着时间的推移而降低。或者更好 select pid 并检查该 pid 占用的资源。

顺便说一句,对于较长的查询,请查看 pg_stat_statements - 查看它们如何随时间变化可以让您对负载如何变化有一些预期