pg_stat_statements 入门

本页目录

img

查询优化的两个分支

查询优化有两个主要的分支:

  1. "微观"优化:分析和改进特定的查询。主要工具是 EXPLAIN。
  2. "宏观"优化:分析整个或大部分工作负载,进行细分,研究其特性,从上到下识别并改进表现最差的部分。主要工具是 pg_stat_statements(以及其扩展或替代方案)、等待事件分析和 PostgreSQL 日志。

今天我们将重点讨论如何从基础开始,阅读和使用 pg_stat_statements,并逐步利用它的数据进行宏观优化。

pg_stat_statements 基础

pg_stat_statements 扩展 (简称为 "pgss") 已经成为宏观分析的事实标准。

它跟踪所有查询,并将它们聚合到查询组中 — 即"标准化查询",其中参数会被去除。

有一些值得注意的限制:

pg_stat_statements 视图包含三种类型的列:

  1. queryid – 标准化查询的标识符。在最新的 PostgreSQL 版本中,它还可以用于将 pgss 的数据与 pg_stat_activity 和 PostgreSQL 日志连接(JOIN)。需要注意的是:queryid 的值可能是负数。
  2. 描述性的列:包括数据库 ID (dbid)、用户 ID (userid) 和查询本身 (query)。
  3. 指标:大部分指标都是累积的,例如 calls、total_time、rows 等。非累积指标包括 stddev_plan_time、stddev_exec_time、min_exec_time 等。在这篇文章中,我们主要关注累积指标。

// 注:在下文中,我有时会将标准化查询称为"查询组"或简称为"组"。

我们来提一些在宏观优化中最常用的指标 (完整列表请参阅文档):

  1. calls – 此查询组 (标准化查询) 的调用次数。

  2. total_plan_time 和 total_exec_time – 该查询组的规划和执行的聚合持续时间 (请再次记住:失败的查询不会被跟踪,包括那些由于 statement_timeout 而失败的查询)。

  3. rows – 此查询组中的查询返回行数。

  4. shared_blks_hit 和 shared_blks_read – 来自缓冲池的命中和读取操作次数。这里有两个重要的注意点:

    • 此处的 "read" 是指从缓冲池读取——这不一定意味着物理读取磁盘,因为数据可能已缓存于操作系统的页面缓存中。因此,我们不能直接认为这些读取来自磁盘。一些监控系统会犯这个错误,但在某些情况下,这种细微差别对于我们的分析能否得出正确结论至关重要。
    • "blocks hit" 和 "blocks read" 的名称可能会产生误导,暗示我们在讨论数据量 — 块 (缓冲区) 的数量。虽然这些值可以聚合,但我们必须记住同一个缓冲区可能会被多次读取或命中。因此,与其说 "blocks have been hit",不如说 "blocks hits"。
  5. wal_bytes – 此查询组中查询写入 WAL 的字节数。

还有许多其他有趣的指标,建议阅读文档来了解它们 (文档)。

处理 pgss 中的累积指标

要读取和解释 pgss 中的数据,需要以下三个步骤:

  1. 获取两个时间点对应的快照。
  2. 计算每个累积指标的差值,以及这两个点之间的时间差。
    • 一个特殊情况是,第一个点是统计数据收集的开始时刻。在 PostgreSQL 14 及更新版本中,有一个单独的视图 pg_stat_statements_info,其中包含 pgss 统计数据上次重置的时间信息。不幸的是,在 PostgreSQL 13 及更早版本中,此信息未被存储。
  3. (最有趣的部分!) 对每个累积指标的差值计算三种衍生指标——假设 M 是我们的指标:a. dM/dt – 指标 M 的基于时间的微分。 b. dM/dc – 基于调用次数的微分 (将在下一篇文章中详细解释)。 c. %M – 该标准化查询在整个工作负载中指标 M 所占的百分比。

第 3 步不仅可以应用于单个主机上的特定标准化查询,还可以应用于更大的组,例如:

如果您的监控系统支持 pgss,那么您无需手动处理快照。不过,请注意,我个人不知道有任何监控工具可以完美支持 pgss,并保留本文中讨论的所有信息 (而且我研究过不少 PostgreSQL 监控工具)。

假设您已经成功获取了 pgss 的两个快照 (记得记录它们的收集时间戳) 或使用了适当的监控工具,现在我们来看看前面讨论的三种衍生指标的实际意义。

衍生指标 1:基于时间的微分

这就是 pgss 相关使用指南的第一部分。在接下来的部分中,我们将讨论 dM/dc 和 %M,以及基于 pgss 进行宏观优化的其他实用内容。

如果你觉得这篇文章有帮助,请分享给你的同事以及任何使用 PostgreSQL 的人。

讨论与补充

在 GitHub 查看讨论

支持作者

感谢支持 PostgreSQL Howto 的长期维护。

微信赞赏码

读者交流群

二维码若已过期,可通过公众号 PostgreSQL 学徒或邮件联系。

PostgreSQL 学徒读者交流群二维码