想象一下,你在开发一个应用,结果有个查询突然成了数据库里最耗资源的。你开始发现应用卡顿、出错。这时候 EXPLAIN 就登场了,它能帮你搞清楚到底哪里出问题了。基于 EXPLAIN 的分析来优化查询,可以帮你省资源、省时间,还能让用户用你的应用更爽。
EXPLAIN 就是让你能“透视” PostgreSQL,看看数据库到底打算怎么执行你的查询。它会告诉你会不会用到索引,还是直接全表扫描,优化器会做哪些步骤,顺序是啥,中间结果大概有多大。
换句话说,EXPLAIN 能让你知道执行查询时会发生啥:这个查询“重不重”,大概要处理多少行,会用到哪些资源。遇到查询突然变慢,用它查原因特别香。
EXPLAIN 就像黑暗里的手电筒:有了它你能看到底层发生了啥,哪里出岔子一目了然。
EXPLAIN 命令语法
来看看 EXPLAIN 的基本语法:
EXPLAIN 你的_SQL_查询;
查询示例:
EXPLAIN SELECT * FROM students WHERE age > 20;
你运行这个命令时,PostgreSQL 不会真的执行查询。它只会给你看执行计划。就像盖房子前先看草图——提前知道会发生啥,避免踩坑。
输出示例:
Seq Scan on students (cost=0.00..35.00 rows=7 width=37)
Filter: (age > 20)
这个输出看着有点吓人,别慌——我们马上拆解下它的主要部分。
基础执行计划解析
来拆解下刚才的结果:
Seq Scan on students —— 这意思是 PostgreSQL 会把
students表全表扫描(顺序扫描)。这不一定是坏事,但表大了Seq Scan就慢了。cost=0.00..35.00 —— 这是操作的成本估算:
Startup Cost:操作的起始成本(这里是0.00)。Total Cost:操作完成的总成本(这里35.00)。
rows=7 —— PostgreSQL 估计
age > 20这个条件能查出 7 行。这叫“基数”(cardinality)。如果你看到估算很离谱,可能是表统计信息过时了。width=37 —— 这是一行的平均字节数。
Filter: (age > 20) —— PostgreSQL 会对每行都用这个过滤条件。
所以 EXPLAIN 的输出能让你了解 PostgreSQL 的策略和假设。你可以用这些信息来优化查询。
EXPLAIN 命令选项
虽然基础 EXPLAIN 已经很有用,你还可以加这些选项让它更强:
ANALYZE
加上这个选项,PostgreSQL 不光给你看计划,还会真的执行查询,给你实际数据。比如:
EXPLAIN ANALYZE SELECT * FROM students WHERE age > 20;
这样你能对比 PostgreSQL 的估算和实际执行,看看准不准。
VERBOSE
显示更多细节,适合深度分析。比如:
EXPLAIN VERBOSE SELECT * FROM students WHERE age > 20;
BUFFERS
显示查询执行时内存缓冲区的使用情况。要和 ANALYZE 一起用:
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM students WHERE age > 20;
COSTS
你可以用这个选项隐藏或显示成本信息(cost):
EXPLAIN (COSTS OFF) SELECT * FROM students WHERE age > 20;
FORMAT
计划输出还能用别的格式,比如 JSON 或 XML。比如:
EXPLAIN (FORMAT JSON) SELECT * FROM students WHERE age > 20;
EXPLAIN 使用示例
假设你有个 university 数据库,里面有 students 表。你想查所有年龄大于 20 岁的学生:
EXPLAIN SELECT * FROM students WHERE age > 20;
输出可能是:
Seq Scan on students (cost=0.00..35.00 rows=7 width=37)
Filter: (age > 20)
就像前面说的,这是顺序扫描 Seq Scan,表大时效率低。
现在我们给 age 列建个索引,看看计划会不会变:
CREATE INDEX age_index ON students(age);
EXPLAIN SELECT * FROM students WHERE age > 20;
输出:
Index Scan using age_index on students (cost=0.15..4.23 rows=7 width=37)
Index Cond: (age > 20)
现在 PostgreSQL 用了索引扫描(Index Scan),通常比全表扫描快,尤其表大的时候。
常见问题和坑
为啥有索引查询还是慢?
可能是查询返回的行太多,导致用索引没啥优势。也可能索引本身不优或者没更新。
如果 EXPLAIN 输出看不懂咋办?
先从简单查询入手,一步步看执行计划的每个节点。
怎么知道表统计信息是不是过时了?
执行 ANALYZE students
啥时候用不带 ANALYZE 的 EXPLAIN?
当你只想看计划,不想真的执行(比如那些会改数据的查询)。
GO TO FULL VERSION