pg_stat_statements 深入使用
本页目录
前两篇文章:

第三类衍生指标:百分比
现在,让我们来研究第三类衍生指标:某个查询组 (标准化查询或更大的组,例如"特定用户的所有语句"或"所有 UPDATE 语句") 在整个工作负载中所占的百分比,基于指标 M。
如何计算:首先,针对所有查询组应用基于时间的微分 (如第一部分中讨论的 dM/dt),然后将特定查询组的值除以所有查询组的总和。
%M 的可视化与解读
虽然 dM/dt 给我们提供了绝对值,如每秒调用次数或 GiB/sec,但 %M 值是相对指标。这些值帮助我们识别工作负载中各个方面的"主要参与者" — 频率、时间、IO 操作等。
通过分析相对值,我们可以理解每个优化方向的潜在收益大小,并优先处理最具潜力的优化。例如:
- 如果 QPS 的绝对值看起来很高 — 比如 1000 次调用/秒 — 但它仅占整体工作负载的
3%,那么减少这一查询不会带来太大的收益。如果我们关心的是 QPS,我们需要优化其他查询组。 - 然而,如果我们有 1000 次调用/秒,并且它占了整体工作负载的
50%,那么单次优化步骤 — 比如将其减少到 10 次调用/秒 — 这将帮助我们减少几乎一半的 QPS。
在较大的系统中处理比例值的一种方法是对较大比例值做出反应,将相应的查询组作为优化候选项。例如,在具有大量查询组的系统中,可能有必要使用以下方法:
- 定期针对某些指标 (例如
calls、total_exec_time、total_plan_time、shared_blks_dirtied、wal_bytes) 构建 Top-10 列表,显示具有最大%M值的查询组。 - 如果某个查询组在某些指标上是主要贡献者 — 例如,>20% — 则应考虑将此查询作为优化的候选项。例如,在大多数情况下,我们不希望单个查询组占据
total_exec_time总和的 1/2 ( totaltotal_exec_time,抱歉使用了赘语)。在某些情况下,可以决定某个查询不需要优化 — 在这种情况下,我们将该组标记为排除项,并在下次分析中跳过它。
对比例的分析也可以在监控系统中通过可视化方式隐式完成:观察 dM/dt 图表 (例如 QPS,每秒块命中次数),我们可以直观地理解哪个查询组在整个工作负载中对特定指标 M 的贡献最大。然而,为此,图表需要"堆叠式"显示。
如果我们处理两个快照,那么明确获取这些值是有意义的。此外,出于可视化目的,为我们分析的每个指标绘制一个饼图也是有意义的。
%M 示例
%M,M是调用次数calls— 这为我们提供了 QPS 的比例。例如,如果我们通常有约10k QPS,但如果某个查询组负责约7k QPS,这可能被认为是不正常的,需要在客户端 (通常是应用代码) 进行优化。%M,M是total_plan_time + total_exec_time— 服务器处理特定查询组所花费时间的百分比。例如,如果绝对值是20 秒/秒(负载相当大的系统——Postgres 每秒需要花费 20 秒来处理查询),并且某个查询组占了该指标的 75%,这意味着我们需要重点优化该查询组。优化方法:- 如果 QPS (
calls/second) 很高,那么首先我们需要减少它。 - 如果平均延迟 (
total_exec_time,或较少见的total_plan_time或两者) 较高,那么我们需要使用EXPLAIN和EXPLAIN (ANALYZE, BUFFERS)进行微观优化。 - 在某些情况下,我们需要结合两种优化方向。
- 如果 QPS (
%M,M是shared_blks_dirtied— 分析查询组在缓冲池中执行的更改所占百分比。这种分析可以帮助我们识别工作负载中的写密集部分,并找到减少检查点次数和磁盘 IO 量的机会。%M,M是wal_bytes— 写入 WAL 的字节数百分比。这帮助我们识别优化 WAL 生成量最有影响的查询组。
总结:三大宏观优化目标及其使用方法
现在,通过我们在前两部分中描述的分析方法,让我们仅基于一个指标 total_exec_time 来考虑三种常见的宏观优化类型。
理解这三种方法 (然后将这种逻辑应用于其他指标) 可以帮助你理解如何设计监控仪表盘。
- 宏观优化旨在减少资源消耗。在这里,我们首先希望减少 CPU 利用率、内存和磁盘 IO 操作。为此,我们需要使用
dM/dt类型的衍生指标 — Postgres 每秒处理查询所花费的秒数。减少这一指标 (整个服务器的聚合 "total" 值,以及在其中起重要作用的前 N 个组) 是我们的目标。此外,我们可能还想考虑其他指标,例如shared_blks_***,但时间可能是最好的起点。这种优化可以帮助我们进行容量规划、基础设施成本优化,并降低资源耗尽的风险。 - 宏观优化旨在改善用户体验。在这里,我们希望用户有最佳体验,因此在 OLTP 场景中,我们应重点关注平均延迟,并以减少它们为目标。因此,我们将使用
dM/dc— 每个查询平均持续的秒数 (或毫秒)。如果在上一种优化类型中,我们希望在监控系统中看到按dM/dt值 (以seconds/second为单位) 排序的前 N 个查询组,这里我们希望按平均延迟 (以秒为单位) 排序的前 N 个组。通常,这会给我们一个非常不同的查询集 — 这些查询可能 QPS 较低,但延迟最差,最让用户感到烦恼。在某些情况下,在这种分析中,我们可能想排除 QPS 较低的查询组 (例如 QPS < 1 call/sec 的那些) 或排除一些工作负载部分,如数据导出活动,它们不可避免地有较长的延迟。 - 宏观优化旨在平衡工作量。这是较为罕见的一种优化类型,但这正是 %M 发挥作用的地方。开发我们的应用程序时,我们可能想不时检查
total_exec_time + total_plan_time的前 N 个百分比,并识别占比最大的查询组 — 正如我们之前讨论的那样。
附加内容:播客集
相关的 Postgres.FM 播客集:
这就是我们目前对 pgss 的讨论。当然,这不是完整的指南,我们可能会在未来再次讨论这个重要的扩展。
如有任何问题或其他反馈,请告诉我!