帮你快速理解、总结文档立即下载

性能监控插件 pg_stat_monitor

最近更新时间:2026-07-21 09:53:01

我的收藏
云数据库 PostgreSQL 提供性能监控插件 pg_stat_monitor,本文为您介绍关于性能监控插件 pg_stat_monitor 的说明及使用方法。

概述

pg_stat_monitor 是一个 PostgreSQL 查询性能监控插件。该插件基于 pg_stat_statements 的统计思路扩展实现,提供按时间窗口聚合的 SQL 执行统计、计划统计、错误信息、访问对象、客户端信息、直方图分布等观测能力,便于定位慢 SQL、分析负载变化和排查性能问题。

支持版本

v17.10_r1.19、v18.4_r1.10及以上版本。

使用限制

pg_stat_monitor 需要通过 shared_preload_libraries 在数据库启动阶段加载。未预加载时可以创建扩展对象,但核心统计功能不会生效,调用统计函数时可能提示插件未通过 shared_preload_libraries 加载。
修改 pg_stat_monitor.pgsm_max、pg_stat_monitor.pgsm_query_max_len、pg_stat_monitor.pgsm_max_buckets、pg_stat_monitor.pgsm_bucket_time、pg_stat_monitor.pgsm_histogram_*、pg_stat_monitor.pgsm_query_shared_buffer、pg_stat_monitor.pgsm_enable_overflow 等 postmaster 级参数后,需要重启实例生效。
插件会在全局执行链路中注册解析、计划、执行、Utility、错误日志等 Hook。建议在生产环境开启前进行压测,评估 CPU、内存和共享内存开销。
pg_stat_monitor 视图默认授予 PUBLIC 查询权限,但跨用户查询文本、执行计划和客户端 IP 会按权限进行遮蔽。对于安全要求较高的实例,建议收敛视图权限,仅授权给 DBA 或监控账号。
插件当前代码声明运行依赖 PostgreSQL 14 及以上版本。当前 C 代码版本号为2.4.0,可通过 pg_stat_monitor_version() 查询。
如同时启用 pg_stat_statements,建议在 shared_preload_libraries 中同时配置两个插件,并关注两者对 Utility 语句统计 Hook 的影响。

创建插件

配置预加载参数

检查 shared_preload_libraries 是否已包含 pg_stat_monitor:
SHOW shared_preload_libraries;

创建扩展

重启完成后,在需要查看统计信息的数据库中创建扩展:
CREATE EXTENSION pg_stat_monitor;
检查插件是否创建成功:
SELECT extname, extversion
FROM pg_extension
WHERE extname = 'pg_stat_monitor';
查看插件运行版本:
SELECT pg_stat_monitor_version();
说明:
pg_stat_monitor 的共享内存统计是实例级采集,但扩展对象和 pg_stat_monitor 视图需要在具体数据库中创建后才能查询。
如果需要在多个数据库中查询该视图,需要分别在对应数据库执行 CREATE EXTENSION pg_stat_monitor;。

参数说明

您可以通过 pg_settings 查看插件参数:
SELECT name, setting, unit, context, vartype, source, min_val, max_val, enumvals
FROM pg_settings
WHERE name LIKE 'pg_stat_monitor.%'
ORDER BY name;

共享内存和时间窗口参数

参数
默认值
生效级别
取值范围
说明
pg_stat_monitor.pgsm_max
256MB
postmaster
10MB - 10240MB
SQL 元数据统计使用的最大共享内存大小。
pg_stat_monitor.pgsm_query_shared_buffer
20MB
postmaster
1MB - 10000MB
查询文本使用的共享内存大小。
pg_stat_monitor.pgsm_query_max_len
2048B
postmaster
1024B - INT_MAX
单条 SQL 文本最大保存长度。
pg_stat_monitor.pgsm_max_buckets
10
postmaster
1 - 20000
保留的时间窗口数量。
pg_stat_monitor.pgsm_bucket_time
60s
postmaster
1s - INT_MAX
每个 bucket 的时间长度。
pg_stat_monitor.pgsm_enable_overflow
on
postmaster
on/off
允许统计数据超过共享内存后继续使用动态共享区域扩展。
说明:
pgsm_max_buckets × pgsm_bucket_time 决定可观察的历史时间跨度。
pgsm_enable_overflow 默认开启,可提升高基数 SQL 场景下的可观测性,但也可能增加内存和 swap 压力。生产环境建议结合实例规格评估后配置。

采集行为参数

参数
默认值
生效级别
说明
pg_stat_monitor.pgsm_track
top
user
控制采集层级,支持 none、top、all。
pg_stat_monitor.pgsm_track_utility
on
user
是否采集 Utility 命令,例如 DDL、VACUUM 等。
pg_stat_monitor.pgsm_track_planning
off
user
是否采集计划阶段统计信息。
pg_stat_monitor.pgsm_track_application_names
on
user
是否采集 application_name。
pg_stat_monitor.pgsm_enable_pgsm_query_id
on
user
是否生成 pgsm_query_id,用于跨库、跨集群比较规范化 SQL。
pg_stat_monitor.pgsm_normalized_query
off
user
是否保存规范化 SQL。开启后常量会被参数占位符替换。
pg_stat_monitor.pgsm_enable_query_plan
off
user
是否采集查询计划文本。
pg_stat_monitor.pgsm_extract_comments
off
user
是否提取 SQL 注释并写入 comments 字段。
pgsm_track 参数取值说明:
取值
说明
none
不采集 SQL 统计。
top
仅采集顶层语句。
all
采集顶层语句和函数、DO 块等内部嵌套语句。
示例:
SET pg_stat_monitor.pgsm_track = 'all';
SET pg_stat_monitor.pgsm_normalized_query = on;
SET pg_stat_monitor.pgsm_track_planning = on;

直方图参数

参数
默认值
生效级别
取值范围
说明
pg_stat_monitor.pgsm_histogram_min
1ms
postmaster
0 - 50000000ms
响应时间直方图最小边界。
pg_stat_monitor.pgsm_histogram_max
100000ms
postmaster
10 - 50000000ms
响应时间直方图最大边界。
pg_stat_monitor.pgsm_histogram_buckets
20
postmaster
2 - 50
响应时间直方图 bucket 数。
说明:
pgsm_histogram_min 必须小于 pgsm_histogram_max。
插件会额外维护低于最小边界和高于最大边界的响应时间分布,用于展示完整调用分布。

查看 SQL 统计

插件创建后,您可以通过 pg_stat_monitor 视图查看采集到的 SQL 统计信息。

查看最近 SQL

SELECT bucket,
bucket_start_time,
datname,
username,
application_name,
queryid,
pgsm_query_id,
calls,
rows,
mean_exec_time,
query
FROM pg_stat_monitor
ORDER BY bucket_start_time DESC, calls DESC
LIMIT 20;

查看耗时最高的 SQL

SELECT datname,
username,
calls,
total_exec_time,
mean_exec_time,
max_exec_time,
rows,
query
FROM pg_stat_monitor
ORDER BY total_exec_time DESC
LIMIT 20;

查看平均耗时最高的 SQL

SELECT datname,
username,
calls,
mean_exec_time,
min_exec_time,
max_exec_time,
stddev_exec_time,
query
FROM pg_stat_monitor
WHERE calls > 0
ORDER BY mean_exec_time DESC
LIMIT 20;

查看指定对象相关 SQL

relations 字段保存语句访问的表或视图名称,可用于根据对象定位相关 SQL:
SELECT datname,
username,
calls,
total_exec_time,
relations,
query
FROM pg_stat_monitor
WHERE relations @> ARRAY['public.orders']
ORDER BY total_exec_time DESC;
如果对象名中未带 schema,可先直接展开查看:
SELECT query, relations
FROM pg_stat_monitor
WHERE relations IS NOT NULL
ORDER BY query;

查看错误 SQL

插件会通过错误日志 Hook 记录 SQL 执行过程中的错误级别、SQLSTATE 和错误消息:
SELECT datname,
username,
query,
decode_error_level(elevel) AS error_level,
sqlcode,
message,
calls
FROM pg_stat_monitor
WHERE elevel IS NOT NULL
AND elevel <> 0
ORDER BY bucket_start_time DESC;

查看 SQL 执行计划

默认不采集执行计划。如需临时排查,可在会话中开启:
SET pg_stat_monitor.pgsm_enable_query_plan = on;
SELECT * FROM your_table WHERE id = 1;

SELECT query, planid, query_plan
FROM pg_stat_monitor
WHERE query_plan IS NOT NULL
ORDER BY bucket_start_time DESC
LIMIT 10;
说明:
执行计划采集会增加开销,建议仅在诊断场景临时开启。
非当前用户或非 pg_read_all_stats 成员查询其他用户记录时,query 和 query_plan 会显示为 <insufficient privilege>。

查看 SQL 注释标签

默认不提取 SQL 注释。如需基于注释传入业务标签,可开启:
SET pg_stat_monitor.pgsm_extract_comments = on;

SELECT 1 /* { "application": "order-service", "trace_id": "demo" } */;

SELECT query, comments
FROM pg_stat_monitor
WHERE comments IS NOT NULL
ORDER BY bucket_start_time DESC;
说明:
SQL 注释可能包含业务标识或敏感信息,生产环境开启前请评估视图访问权限。

查看响应时间直方图

查看直方图边界:
SELECT range();
查看某条 SQL 在指定 bucket 下的响应时间分布:
SELECT bucket, queryid, query
FROM pg_stat_monitor
ORDER BY calls DESC
LIMIT 1;
将上一步得到的 bucket 和 queryid 传入 histogram:
SELECT *
FROM histogram(<bucket>, <queryid>) AS h(range text, freq int, bar text);
返回字段说明:
字段
说明
range
响应时间区间。
freq
落入该区间的调用次数。
bar
基于 freq 生成的文本柱状图。

视图字段说明

pg_stat_monitor 视图会根据 PostgreSQL 版本创建对应字段。当前代码中的最新视图主要包含以下字段类别。

基础维度

字段
说明
bucket
统计所属 bucket 编号。
bucket_start_time
bucket 起始时间。
bucket_done
bucket 是否已结束。
userid / username
执行用户 OID 和用户名。
dbid / datname
数据库 OID 和数据库名。
client_ip
客户端 IP。非当前用户或非 pg_read_all_stats 成员可能显示为空。
application_name
会话 application_name。
toplevel
是否为顶层语句。

SQL 标识和文本

字段
说明
queryid
PostgreSQL 内核生成的 query ID。
pgsm_query_id
插件生成的规范化 query ID,可用于跨数据库、跨集群比较同类 SQL。
top_queryid
顶层语句 query ID。
query
SQL 文本。受权限控制。
top_query
顶层 SQL 文本。
comments
SQL 注释内容,需要开启 pgsm_extract_comments。
planid
执行计划 ID。
query_plan
执行计划文本,需要开启 pgsm_enable_query_plan。受权限控制。
relations
SQL 访问的关系对象数组。
cmd_type / cmd_type_text
命令类型编码和文本,例如 SELECT、UPDATE、INSERT、DELETE、MERGE、UTILITY。

执行统计

字段
说明
calls
调用次数。
rows
返回或影响行数。
total_exec_time
总执行耗时,单位毫秒。
min_exec_time
最小执行耗时,单位毫秒。
max_exec_time
最大执行耗时,单位毫秒。
mean_exec_time
平均执行耗时,单位毫秒。
stddev_exec_time
执行耗时标准差。
resp_calls
响应时间直方图计数数组。
cpu_user_time
用户态 CPU 时间。
cpu_sys_time
系统态 CPU 时间。

计划统计

字段
说明
plans
计划次数。
total_plan_time
总计划耗时,单位毫秒。
min_plan_time
最小计划耗时,单位毫秒。
max_plan_time
最大计划耗时,单位毫秒。
mean_plan_time
平均计划耗时,单位毫秒。
stddev_plan_time
计划耗时标准差。

IO、WAL、JIT 和并行统计

字段
说明
shared_blks_hit/read/dirtied/written
共享缓冲区命中、读取、脏页、写出块数。
local_blks_hit/read/dirtied/written
本地缓冲区命中、读取、脏页、写出块数。
temp_blks_read/written
临时块读取和写入数量。
shared_blk_read_time/shared_blk_write_time
共享块读写耗时。
local_blk_read_time/local_blk_write_time
本地块读写耗时。
temp_blk_read_time/temp_blk_write_time
临时块读写耗时。
wal_records wal_fpi wal_bytes / wal_buffers_full
WAL 相关统计。
jit_functions、jit_generation_time 等
JIT 相关统计。
parallel_workers_to_launch / parallel_workers_launched
计划启动和实际启动的并行 worker 数。
stats_since / minmax_stats_since
统计起始时间。

错误信息

字段
说明
elevel
PostgreSQL 内部错误级别编码。
sqlcode
SQLSTATE 文本。
message
错误消息文本。
您可以使用 decode_error_level(elevel) 将错误级别转换为可读文本。

函数说明

函数
说明
权限
pg_stat_monitor_version()
返回插件 C 代码版本号。
默认可执行。
pg_stat_monitor_reset()
清空当前统计信息。
安装脚本中已从 PUBLIC 回收权限。
pg_stat_monitor_internal(showtext boolean)
内部 SRF 函数,供视图使用。
安装脚本中授予 PUBLIC 执行权限。
get_histogram_timings()
返回当前直方图边界字符串。
默认可执行。
range()
将直方图边界转换为数组。
默认可执行。
histogram(bucket int, queryid int8)
返回指定 SQL 在指定 bucket 下的响应时间分布。
默认可执行。
get_cmd_type(cmd_type int)
将命令类型编码转换为文本。
默认可执行。
decode_error_level(elevel int)
将错误级别编码转换为文本。
默认可执行。
说明:
pgsm_create_view()、pgsm_create_14_view()、pgsm_create_15_view()、pgsm_create_17_view()、pgsm_create_18_view() 等函数用于安装阶段按内核版本创建视图,安装后已从 PUBLIC 回收权限,不建议业务直接调用。
pg_stat_monitor_internal() 是内部函数,日常使用建议通过 pg_stat_monitor 视图访问。

功能示例

按时间窗口观察 SQL 负载

pg_stat_monitor 与 pg_stat_statements 的主要差异之一是引入 bucket。每个 bucket 代表一个时间窗口,可用于观察短时间内的负载变化。
SELECT bucket,
bucket_start_time,
count(*) AS sql_count,
sum(calls) AS total_calls,
sum(total_exec_time) AS total_exec_time
FROM pg_stat_monitor
GROUP BY bucket, bucket_start_time
ORDER BY bucket_start_time DESC;

开启规范化 SQL

开启后,常量会被替换为占位符,便于聚合相同形态 SQL:
SET pg_stat_monitor.pgsm_normalized_query = on;

SELECT * FROM orders WHERE id = 1;
SELECT * FROM orders WHERE id = 2;

SELECT query, calls
FROM pg_stat_monitor
WHERE query LIKE '%orders%'
ORDER BY calls DESC;

观察嵌套 SQL

默认 pgsm_track = 'top' 只跟踪顶层语句。如果需要观察函数或 DO 块内部 SQL,可设置为 all:
SET pg_stat_monitor.pgsm_track = 'all';
排查结束后建议恢复为 top:
SET pg_stat_monitor.pgsm_track = 'top';

查看计划阶段耗时

默认不采集计划阶段统计。需要排查优化器耗时时可开启:
SET pg_stat_monitor.pgsm_track_planning = on;

SELECT query,
plans,
total_plan_time,
mean_plan_time,
calls,
total_exec_time,
mean_exec_time
FROM pg_stat_monitor
ORDER BY total_plan_time DESC
LIMIT 20;

清空统计信息

SELECT pg_stat_monitor_reset();
说明:
该函数会清空全局统计信息,默认未授予 PUBLIC。建议仅允许 DBA 或监控管理账号使用。

权限和安全建议

插件安装脚本中默认:
GRANT SELECT ON pg_stat_monitor TO PUBLIC;
GRANT EXECUTE ON FUNCTION pg_stat_monitor_internal TO PUBLIC;
REVOKE ALL ON FUNCTION pg_stat_monitor_reset FROM PUBLIC;
代码中对部分敏感字段做了权限控制:
当前用户可以查看自己的 query、query_plan 和 client_ip。
超级用户或 pg_read_all_stats 成员可以查看全部用户的 query、query_plan 和 client_ip。
其他用户查看非本人记录时,query 和 query_plan 显示为 <insufficient privilege>,client_ip 显示为空。
生产环境建议:
REVOKE SELECT ON pg_stat_monitor FROM PUBLIC;
REVOKE EXECUTE ON FUNCTION pg_stat_monitor_internal(boolean) FROM PUBLIC;
GRANT SELECT ON pg_stat_monitor TO pg_read_all_stats;
说明:
message、comments、relations、application_name 等字段可能包含业务信息或对象信息。若实例存在多租户或权限隔离要求,建议不要向普通用户开放完整视图。
pgsm_enable_query_plan、pgsm_extract_comments 建议仅在诊断窗口开启。
pgsm_enable_overflow 默认开启,建议结合实例规格和 SQL 基数评估资源风险。

推荐配置

通用生产观测配置示例:
pg_stat_monitor.pgsm_max = 256MB
pg_stat_monitor.pgsm_query_shared_buffer = 20MB
pg_stat_monitor.pgsm_query_max_len = 2048
pg_stat_monitor.pgsm_max_buckets = 10
pg_stat_monitor.pgsm_bucket_time = 60

pg_stat_monitor.pgsm_track = 'top'
pg_stat_monitor.pgsm_track_utility = on
pg_stat_monitor.pgsm_track_planning = off
pg_stat_monitor.pgsm_normalized_query = on
pg_stat_monitor.pgsm_enable_query_plan = off
pg_stat_monitor.pgsm_extract_comments = off
高安全要求场景建议:
pg_stat_monitor.pgsm_enable_overflow = off
pg_stat_monitor.pgsm_enable_query_plan = off
pg_stat_monitor.pgsm_extract_comments = off
pg_stat_monitor.pgsm_track = 'top'
诊断慢 SQL 时可在会话级临时开启:
SET pg_stat_monitor.pgsm_track_planning = on;
SET pg_stat_monitor.pgsm_enable_query_plan = on;
SET pg_stat_monitor.pgsm_track = 'all';

卸载插件

在数据库中删除扩展:
DROP EXTENSION pg_stat_monitor;

常见问题

为什么创建扩展后没有统计数据?

请确认插件已通过 shared_preload_libraries 预加载,并且数据库实例已重启:
SHOW shared_preload_libraries;
如未包含 pg_stat_monitor,请配置后重启实例。

为什么看不到其他用户的 SQL 文本?

这是权限控制行为。非当前用户、非超级用户、非 pg_read_all_stats 成员查询其他用户记录时,query 和 query_plan 会显示为 <insufficient privilege>。
如监控账号需要查看全部 SQL,可授予:
GRANT pg_read_all_stats TO monitor_user;

为什么修改部分参数后不生效?

context = postmaster 的参数只能在启动时生效,修改后需要重启数据库。可通过如下命令查看参数级别:
SELECT name, context, pending_restart
FROM pg_settings
WHERE name LIKE 'pg_stat_monitor.%'
ORDER BY name;

为什么 query_plan 为空?

query_plan 默认不采集。需要参考如下命令开启:
SET pg_stat_monitor.pgsm_enable_query_plan = on;
同时,只有 SELECT 类查询才会采集执行计划。

为什么 comments 为空?

comments 默认不采集。需要参考如下命令开启:
SET pg_stat_monitor.pgsm_extract_comments = on;

为什么 bucket 中的统计会变化?

pg_stat_monitor 按时间窗口聚合统计。当前 bucket 仍在写入,bucket_done = false;历史 bucket 已结束,bucket_done = true。当 bucket 数超过 pgsm_max_buckets 后,旧 bucket 会被复用。