PostgreSQL 查看慢查询(Slow Query)
慢查询有两个观察维度:日志侧(事后翻日志,靠
log_min_duration_statement/auto_explain记录)和实时侧(看正在跑/累计跑的 SQL,靠pg_stat_activity/pg_stat_statements)。
1. 日志侧:记录慢查询
log_min_duration_statement(最基础)
在 postgresql.conf 中设置,超过该毫秒数的语句会连同耗时写入日志:
- 单位毫秒;设
0记录所有语句(日志量会很大,一般不用) - 改后需
reload(pg_ctl reload/SELECT pg_reload_conf();),无需重启 - 效果:日志里出现
duration: 1234.567 ms statement: SELECT ...,配合log_line_prefix里的%m %u %d(时间/用户/库)定位来源
auto_explain(记录慢查询的执行计划)
比裸日志更进一步:自动把慢查询的 EXPLAIN 计划也写进日志,方便事后看 计划是否合理:
shared_preload_libraries = 'auto_explain'
auto_explain.log_min_duration = 1000 # 超过 1s 的语句记录计划
auto_explain.log_analyze = on # 附带真实执行统计(开销更高)
shared_preload_libraries需要重启才生效(与log_min_duration_statement的 reload 不同)。
2. 实时侧:正在跑 / 累计的慢查询
pg_stat_activity(当前正在执行的)
SELECT pid, usename, now() - query_start AS age,
state, wait_event_type, left(query, 200) AS query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY query_start
LIMIT 20;
看到 age 很大且 state = 'active' 的,就是当下的慢查询(详情见 活跃会话诊断)。
pg_stat_statements(累计统计,推荐)
记录每条 SQL 的调用次数、总耗时、平均耗时等,是「反复出现的慢 SQL」 的标准工具:
-- 按累计执行时间排名
SELECT calls,
round(total_exec_time / 1000) AS total_ms,
round(mean_exec_time / 1000) AS mean_ms,
round(max_exec_time / 1000) AS max_ms,
left(query, 200) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
-- 或按平均耗时排名(少而慢的查询)
SELECT calls,
round(mean_exec_time / 1000) AS mean_ms,
round(total_exec_time / 1000) AS total_ms,
left(query, 200) AS query
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
启用步骤:
postgresql.conf加shared_preload_libraries = 'pg_stat_statements'→ 重启CREATE EXTENSION pg_stat_statements;pg_stat_statements_reset();可清空累计值重新观察(PG 14+ 无参形式; PG 9.2–13 需pg_stat_statements_reset(0,0,0);)
版本差异:PG 13+ 列名为
total_exec_time/mean_exec_time/max_exec_time(单位毫秒);9.x–12 为total_time/mean_time/max_time。PG 15+ 默认compute_query_id,可与pg_stat_activity.query_id对应到同一条查询。
3. 定位到具体查询后
- 对嫌疑 SQL 执行
EXPLAIN (ANALYZE, BUFFERS),看扫描方式(Seq Scan vs Index Scan)、rows 估算偏差、Buffer 用量 - 结合
pg_stat_user_indexes看是否有该用的索引没用上(idx_scan = 0) - 若慢的是写入/锁等待场景,参考活跃会话诊断的 锁等待排查点
一句话总结
| 场景 | 用什么 |
|---|---|
| 事后翻日志 | log_min_duration_statement(耗时)→ auto_explain(+ 计划) |
| 现在正在跑的 | pg_stat_activity |
| 反复出现/累计统计 | pg_stat_statements(先装扩展) |
Backlinks (1)
flowchart LR
n0["CRC(循环冗余校验)原理"]
n1["Algorithms"]
n2["Database"]
n3["Bitcask 存储模型(日志结构哈希表)"]
n4["KV 数据库对比"]
n5["KV 数据库"]
n6["PostgreSQL 活跃会话诊断(Active Sessions)"]
n7["PostgreSQL 磁盘占用查看(Table Size / Datafile)"]
n8["PostgreSQL"]
n9["PostgreSQL 内存占用查看(Memory / Buffers / Connections)"]
n10["PostgreSQL 查看慢查询(Slow Query)"]
n11["PostgreSQL WAL 与 LSN"]
n12["Knowledge"]
n13["Cloud"]
n14["Infrastructure"]
n15["Prototypes"]
n1 --> n0
n2 --> n5
n2 --> n8
n4 --> n3
n5 --> n3
n5 --> n4
n8 --> n6
n8 --> n7
n8 --> n9
n8 --> n10
n8 --> n11
n9 --> n6
n9 --> n7
n10 --> n6
n12 --> n1
n12 --> n2
n12 --> n14
n14 --> n13
n15 --> n3
click n0 "../../../algorithms/crc/" "CRC(循环冗余校验)原理"
click n1 "../../../algorithms/" "Algorithms"
click n2 "../../" "Database"
click n3 "../../kv/bitcask/" "Bitcask 存储模型(日志结构哈希表)"
click n4 "../../kv/comparison/" "KV 数据库对比"
click n5 "../../kv/" "KV 数据库"
click n6 "../active-sessions/" "PostgreSQL 活跃会话诊断(Active Sessions)"
click n7 "../disk-usage/" "PostgreSQL 磁盘占用查看(Table Size / Datafile)"
click n8 "../" "PostgreSQL"
click n9 "../memory-usage/" "PostgreSQL 内存占用查看(Memory / Buffers / Connections)"
click n10 "./" "PostgreSQL 查看慢查询(Slow Query)"
click n11 "../wal-lsn/" "PostgreSQL WAL 与 LSN"
click n12 "../../../" "Knowledge"
click n13 "../../../infrastructure/cloud/" "Cloud"
click n14 "../../../infrastructure/" "Infrastructure"
click n15 "../../../../prototypes/" "Prototypes"