EXPLAIN ANALYZE 怎么读:逐字段中文图解
发布:2026-10-02 · 性能优化EXPLAIN入门
看不懂执行计划,性能优化就只能靠猜。本文教你逐字段读 EXPLAIN ANALYZE 输出。
读完可以立刻用本站的 EXPLAIN 中文分析器实战检验。
从一条最简单的计划说起
Seq Scan on orders (cost=0.00..35.50 rows=2550 width=4)
(actual time=0.020..3.100 rows=2600 loops=1)
| 字段 | 含义 | 读懂什么 |
|---|---|---|
cost=0.00..35.50 | 启动成本..总成本(无量纲,非毫秒!) | 磁盘页读取 + CPU 行数的加权估计 |
rows=2550 | 优化器估算输出行数 | 与 actual 的差距就是「统计准不准」 |
width=4 | 平均每行字节数 | 越小说明传给上层的数据越瘦 |
actual time=0.020..3.100 | 单次循环平均的启动..完成耗时(毫秒) | 真实测量值 |
rows=2600 | 实际输出行数 | 与估算差 10 倍以上 → 先 ANALYZE |
loops=1 | 该节点执行的循环次数 | 耗时与行数都是单次循环的平均值 |
最容易犯的错误:看到内层节点 actual time=0.3 就以为它很快——
如果 loops=10000,总耗时约 0.3 × 10000 = 3000ms。
判断一个节点的真实开销,永远用 actual time × loops。
阅读顺序:自底向上
计划树缩进最深的节点最先执行。排查性能问题的顺序:
- 找
Seq Scan且Rows Removed by Filter很大的节点——读了大量行又扔掉,索引缺位; - 找估算/实际偏差 ≥10 倍的节点——统计信息过期,先
ANALYZE再谈别的; - 看
Sort Method: external merge——排序溢出磁盘,work_mem 不够或该建索引; - 看
Buffers: shared hit/read——read 高说明在打磁盘(冷启动或工作集太大)。
BUFFERS:比耗时更稳定的信号
EXPLAIN (ANALYZE, BUFFERS) SELECT ...;
shared hit:从 shared_buffers/shared pool 命中,内存速度;shared read:需要从操作系统/磁盘读。- 第一次执行的 read 高可能只是冷缓存,跑第二次对比才有意义。
常见「病征 → 处方」速查
| 病征 | 处方 |
|---|---|
| 大表 Seq Scan + 高过滤丢弃 | 给 WHERE 列建 B-tree;条件固定可建部分索引 |
| 估算/实际差 ≥10 倍 | ANALYZE 表; 列相关用 CREATE STATISTICS |
| external merge sort | 会话级 SET work_mem='64MB' 或索引消除排序 |
| Nested Loop 内层循环上万次 | 内层表连接列建索引;确认无隐式类型转换 |
| Hash Batches>1 | work_mem 不够,哈希侧先过滤减行 |
两个容易忽略的段落
- Planning Time 很高:表太多/统计信息过载,考虑简化查询或分区裁剪;
- JIT:PG 19 起默认关闭;老版本上偶见「JIT 编译耗时 > 执行耗时」的小查询劣化。
写操作的注意事项
EXPLAIN ANALYZE 会真实执行语句。对 UPDATE/DELETE 先包一层保护:
BEGIN;
EXPLAIN ANALYZE UPDATE accounts SET balance = balance - 10 WHERE id = 1;
ROLLBACK;
下一步
把你的慢查询计划粘进 EXPLAIN 中文分析器, 它会自动完成上面全部检查并给出中文建议——全程在浏览器本地完成,生产计划不怕外泄。
本文为 pgcn.cc 原创内容,转载需授权并保留链接。勘误/投稿: 联系方式。