首页/数据/SQL 速查/pg_stat_statements 找重查询
性能与执行计划72 条

pg_stat_statements 找重查询

按语句模板累计调用次数与执行时间:PG 上做查询负载分析的基础扩展,需要预加载后启用。

SQL 速查数据更新于 2026-10-13

pg_stat_statements 是什么

pg_stat_statements 是 PostgreSQL 的官方扩展,按归一化后的语句模板(常量被替换为占位符)累计调用次数、总执行时间、平均执行时间与扫描行数,是定位「哪条 SQL 吃掉了最多时间」的标准工具。它必须写在 shared_preload_libraries 中并重启实例,再执行 CREATE EXTENSION 才能查询。与慢查询日志相比,它给出的是全局累计视角,更适合找优化优先级。

基本信息

适用平台PostgreSQL 9.4+(字段名随版本变化)
启用方式postgresql.conf 里 shared_preload_libraries = 'pg_stat_statements',重启后 CREATE EXTENSION
版本差异PG13 起为 total_exec_time / mean_exec_time;更早版本是 total_time / mean_time
统计口径按归一化模板合并,同一模板不同常量合成一行
清零方式SELECT pg_stat_statements_reset();

典型使用场景

  • 找出累计耗时最多的 SQL,确定优化顺序
  • 压测前后对比:清零统计后跑同一负载,看变化幅度
  • 定位应用里调用次数异常高的语句,判断是否有循环查询
  • 验证索引优化的真实收益,而不是只看单次 EXPLAIN
  • 与慢查询日志互补:日志看偶发尖峰,扩展看整体占比

启用与排名查询

启用与排名查询
# postgresql.conf 增加下面两行后重启实例
# shared_preload_libraries = 'pg_stat_statements'
# pg_stat_statements.max = 5000      # 最多跟踪的语句模板数

CREATE EXTENSION IF NOT EXISTS pg_stat_statements;   -- 在目标数据库中执行

SELECT calls,
       ROUND(total_exec_time::numeric, 1) AS total_ms,
       ROUND(mean_exec_time::numeric, 2)  AS mean_ms,
       rows,
       ROUND(100 * total_exec_time / SUM(total_exec_time) OVER (), 1) AS pct,
       left(query, 60) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

窗口管理与另一种排序

窗口管理与另一种排序
-- 压测或变更前清零,让统计数据只对应观察窗口
SELECT pg_stat_statements_reset();

-- 找「单次很慢」的语句:平均耗时排序,过滤掉样本太少的模板
SELECT calls, ROUND(mean_exec_time::numeric, 2) AS mean_ms, left(query, 60)
FROM pg_stat_statements
WHERE calls > 10
ORDER BY mean_exec_time DESC
LIMIT 10;

关键列读法

列含义关注点
calls模板被调用次数高频小查询也会堆出很高的总耗时
total_exec_time累计执行时间(毫秒)总时间榜首通常就是优化重点
mean_exec_time平均执行时间反映单次代价,需与 total 结合看
rows返回或影响的累计行数行数远超调用次数说明结果集偏大
shared_blks_read / hit共享块物理读与命中次数命中率低说明缓存不友好
如果查询结果为空,先确认扩展是否真的加载成功:改了配置没重启时 CREATE EXTENSION 会报找不到文件,可用 SELECT * FROM pg_available_extensions WHERE name = 'pg_stat_statements' 确认可用性。
视图里存的是归一化文本,常量已被替换为 $1 这类占位符,看不到具体参数值;要定位「哪个用户/哪批参数慢」,需结合 pg_stat_activity 或应用侧日志。

易错点

  • 只改 shared_preload_libraries 不重启实例,CREATE EXTENSION 直接报错
  • 照搬旧版教程的字段名:PG13 之前叫 total_time / mean_time,写错列名查询报错
  • 只按平均耗时排序而忽略总耗时榜,优化了低频慢查询却放过高频小查询
  • 对比优化前后不看统计窗口:没有先 pg_stat_statements_reset(),历史累计数据把结论掩盖

数据来源与参考

  • PostgreSQL Documentation · pg_stat_statements
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌