PostgreSQL 19: pg_stat_statements 可优化 SQL 计划生成开销

John Doe 三月 2, 2026

pg_stat_statements 是 PostgreSQL 生态中最核心、使用最广泛的 SQL 性能监控扩展,它能持久化记录数据库中所有 SQL 语句的执行次数、耗时、IO 开销等核心指标,是 DBA 定位慢查询、优化数据库性能的必备工具。但长期以来,它存在一个能力缺口:无法跟踪 SQL 语句的计划生成开销。

image

特性提交日志

pg_stat_statements:新增通用计划与自定义计划计数器。

此补丁为 pg_stat_statements 新增了两个计数器:

  • generic_plan_calls(通用计划调用次数)
  • custom_plan_calls(自定义计划调用次数)

这两个计数器分别用于跟踪预编译语句(prepared statement)使用通用计划(generic plan)和自定义计划(custom plan)执行的次数。pg_prepared_statements 的数据仅局限于单个会话,而新增计数器则在查询级别(涵盖顶层和非顶层查询)提供了与 pg_prepared_statements 功能等效的全局统计数据。

讨论:https://postgr.es/m/CAA5RZ0uFw8Y9GCFvafhC=OA8NnMqVZyzXPfv_EePOt+iv1T-qQ@mail.gmail.com

示例

假设我们需要评估系统的计划缓存效率:哪些 SQL 适合复用通用计划降低 CPU 开销,哪些 SQL 必须使用自定义计划保障执行性能,避免出现 “CPU 优化过度导致执行性能下降” 或 “重复优化导致 CPU 占用过高” 的问题。

下面我们就来使用该新特性,优化 OLTP 系统的计划缓存效率。

统计通用计划占比高于 99% 的高频 SQL:

SELECT 
  queryid,
  LEFT(query, 80) AS query_preview,
  calls,
  -- 计算通用计划占比
  generic_plan_calls::NUMERIC / calls AS generic_plan_ratio,
  mean_exec_time
FROM pg_stat_statements
WHERE calls > 1000
  AND generic_plan_ratio > 0.99
ORDER BY calls DESC;

统计自定义计划占比高于 99%、计划生成开销高的高频 SQL:

SELECT 
  queryid,
  LEFT(query, 80) AS query_preview,
  calls,
  -- 计算自定义计划占比
  custom_plan_calls::NUMERIC / calls AS custom_plan_ratio,
  mean_exec_time,
  mean_plan_time
FROM pg_stat_statements
WHERE calls > 1000
  AND custom_plan_ratio > 0.99
ORDER BY total_plan_time DESC;

分类优化策略

  • 通用计划占比高于 99%、执行耗时稳定的 SQL:无需调整,计划复用已有效降低 CPU 开销,符合 OLTP 优化目标。
  • 自定义计划占比高于 99%、高频执行、计划生成耗时高的 SQL:评估是否可通过使用预备语句、存储过程,让优化器选择通用计划,减少重复生成计划的 CPU 开销。
  • 两种计划混用的 SQL:结合业务场景通过plan_cache_mode强制指定计划类型,避免计划切换带来的性能抖动。

非常不错的体验,感谢所有参与的社区人员。

参考

提交日志:https://git.postgresql.org/pg/commitdiff/3357471cf9f5e470dfed0c7919bcf31c7efaf2b9