你可能已经在想:为啥分析 SQL 性能要有两个工具?到底哪个用得多点,EXPLAIN ANALYZE 还是 pg_stat_statements?咱们来聊聊这两种方法,各自的优缺点,以及它们适合用在什么场景。
工具能解决哪些问题
EXPLAIN ANALYZE:这是用来深度分析某个具体 SQL 查询的工具。如果你想知道 PostgreSQL 是怎么执行你的查询的,走了哪些节点,处理了多少行,每一步花了多少时间,这就是你的首选。它能帮你回答:“为啥我这个查询这么慢?”
pg_stat_statements:这是更高层次的监控工具,能看到数据库里所有查询的性能信息。如果你想看整体性能,比如“我数据库里哪些查询最慢?”或者“哪些 SQL 最吃服务器资源?”,那就用它。
什么时候用 EXPLAIN ANALYZE
EXPLAIN ANALYZE 就像你的调试神器,能让你搞清楚 PostgreSQL 到底是怎么跑某个 SQL 的。下面这些场景可以用它:
单个查询的精准优化 如果有人抱怨你应用的某个页面加载半天,你第一步肯定是找到那个慢的 SQL,然后用 EXPLAIN ANALYZE 看看执行计划和实际的执行时间、处理的行数等指标。
选对索引 你新建了索引或者改了索引结构,就可以用 EXPLAIN ANALYZE 看看 PostgreSQL 到底用不用你这个索引。如果不用,说明你这个索引可能没啥用。
调试复杂 SQL 写了个很复杂的 SQL,里面一堆 JOIN 或 WHERE,用 EXPLAIN ANALYZE 看实际的执行计划,能帮你发现瓶颈,比如那些没必要的全表扫描(Seq Scan,老熟人了)。
例子:用 EXPLAIN ANALYZE 优化查询
-- 这个查询跑得很慢
SELECT *
FROM students
WHERE name = 'Alice';
-- 分析执行计划
EXPLAIN ANALYZE
SELECT *
FROM students
WHERE name = 'Alice';
如果你看到用了 Seq Scan,那可能是你忘了建索引:
-- 在 name 字段上建索引
CREATE INDEX idx_students_name ON students(name);
-- 再查一次
EXPLAIN ANALYZE
SELECT *
FROM students
WHERE name = 'Alice';
什么时候用 pg_stat_statements
这个工具用来分析整个系统的性能,下面这些场景很适合:
生产环境监控 pg_stat_statements 能显示一段时间内所有 SQL 的执行统计。你可以通过 total_time 字段很快找到最慢的 SQL。
找“重型”查询 想知道哪些 SQL 最常让数据库吃力?可以按内存命中次数(shared_blks_hit)或者处理的行数(rows)排序。
找高频查询 有时候不是慢查询最麻烦,而是那些执行特别频繁的 SQL。比如有个 SQL 一分钟跑 100 次,哪怕只优化一点点,也能大大减轻服务器压力。
例子:用 pg_stat_statements 找慢查询
-- 查看 SQL 统计信息
SELECT query,
calls,
total_time,
rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 5;
这个查询会显示耗时最多的前 5 个 SQL。
对比:两种方法有啥区别?
| 对比项 | EXPLAIN ANALYZE | pg_stat_statements |
|---|---|---|
| 分析焦点 | 单个具体查询 | 所有查询的全局监控 |
| 细节级别 | 每个执行节点的实际数据 | 每个查询的汇总统计 |
| 使用场景 | 开发阶段用 | 生产环境用 |
| 执行需求 | 会实际执行 SQL 并测量时间 | 不执行 SQL,只聚合数据 |
| 配置难度 | 不用配置 | 需要安装扩展 |
| 资源消耗 | 一次性测量 | 持续收集统计,消耗看负载 |
两个工具一起用才是王道
编程里没有什么银弹,想搞定性能问题,最好两个工具一起用。比如:
先用
pg_stat_statements找出最慢或者最常用的 SQL。再用
EXPLAIN ANALYZE针对这些 SQL 深入分析原因。
实战例子:组合拳
-- 第一步:找最慢的 SQL
SELECT query, total_time, calls
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 1;
-- 第二步:分析这个 SQL
EXPLAIN ANALYZE
<把上一步查出来的 SQL 粘过来>;
常见错误
用 EXPLAIN ANALYZE 和 pg_stat_statements 时,新手经常会踩这些坑:
忽略数据量的真实性。如果你在空表上分析 SQL,
EXPLAIN ANALYZE的结果可能会误导你。一定要保证测试库的数据量跟实际差不多。不管监控的资源消耗。如果生产环境开了
pg_stat_statements,记得合理配置,别让它拖慢数据库。只看理论计划,不看实际执行。
EXPLAIN只给你理论计划,想看真实数据一定要用EXPLAIN ANALYZE。
现在你已经有了对付慢查询的全套武器,不光能解决问题,还能提前预防。PostgreSQL 给了你强大的工具,灵活组合用起来,哪怕系统压力很大,也能跑得飞快!
GO TO FULL VERSION