如果 EXPLAIN 让你像看水晶球一样,能看到 PostgreSQL “打算”怎么执行查询,那 EXPLAIN ANALYZE 就让你变成了真正的侦探,去查明 实际发生了什么。
EXPLAIN 和 EXPLAIN ANALYZE 的主要区别:
EXPLAIN —— 理论,展示 PostgreSQL 计划怎么执行查询。你能看到一些估算值,比如行数 (rows) 和执行代价 (cost)。
EXPLAIN ANALYZE —— 实践。PostgreSQL 真正执行查询,并展示:
- 每一步实际处理的行数。
- 每个操作的真实执行时间。
- 和计划里的估算值(
rows和cost)对比。
举个例子:如果你的查询预计处理 100 行,结果实际处理了 10 000 行,EXPLAIN ANALYZE 马上就会把这个“脏秘密”暴露出来!
基本语法和用法
和 EXPLAIN 一样,EXPLAIN ANALYZE 也很简单。只要在 EXPLAIN 命令后面加上 ANALYZE 就行了。
EXPLAIN ANALYZE
SELECT * FROM students WHERE age > 20;
PostgreSQL 会做这些事:
- 它会执行查询。
- 把每一步的执行计划和真实数据都记录下来。
- 返回完整的查询执行过程描述。
EXPLAIN ANALYZE 提供了哪些数据?
操作的真实执行时间:
Actual Start Time:操作开始的时间。Actual End Time:操作结束的时间。
总共处理的行数:
这有助于你判断计划里的估算(rows)准不准。
缓冲区信息:
比如磁盘和内存缓冲区的使用情况。
EXPLAIN ANALYZE 的使用示例
来看个具体例子。我们有个 students 表,存着学生的数据:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
age INTEGER,
grade FLOAT
);
INSERT INTO students (name, age, grade)
VALUES
('Alice', 22, 4.1),
('Bob', 19, 3.8),
('Charlie', 23, 4.5),
('Diana', 20, 3.9);
我们来查一下年龄大于 20 岁的学生:
EXPLAIN ANALYZE
SELECT * FROM students WHERE age > 20;
结果示例:
Seq Scan on students (cost=0.00..14.00 rows=2 width=116) (actual time=0.025..0.026 rows=2 loops=1)
Filter: (age > 20)
Rows Removed by Filter: 2
Planning Time: 0.032 ms
Execution Time: 0.048 ms
来分析一下结果:
Seq Scan—— 说明 PostgreSQL 用的是顺序扫描表。cost=0.00..14.00—— 这是操作的估算代价。rows=2—— PostgreSQL 预计会返回 2 行(这次猜对了!)。actual time=0.025..0.026—— 实际执行这个操作花了多少毫秒。Rows Removed by Filter: 2—— 有两行被过滤掉了,因为不满足WHERE条件。
理论和实践的对比
这就是 EXPLAIN ANALYZE 的魔力:它能让你看到查询实际是怎么执行的,还能和理论执行计划对比。
我们再来看个复杂点的例子。
EXPLAIN ANALYZE
SELECT * FROM students WHERE age > 20 AND grade > 4.0;
结果示例:
Seq Scan on students (cost=0.00..14.00 rows=1 width=116) (actual time=0.026..0.027 rows=1 loops=1)
Filter: ((age > 20) AND (grade > 4.0))
Rows Removed by Filter: 3
Planning Time: 0.035 ms
Execution Time: 0.057 ms
我们能看到:
- PostgreSQL 用了 0.057 毫秒执行完查询。
- 只有一行(
rows=1)满足WHERE条件。 - 有三行被过滤掉了(
Rows Removed by Filter: 3)。
总结
用 EXPLAIN ANALYZE 能帮你找出瓶颈,理解怎么优化查询。比如:
- 如果
Seq Scan太“重”,可能该加个索引了。 - 如果 PostgreSQL 的估算和实际数据差很多,得检查下表的统计信息(
ANALYZE)或者索引结构。
GO TO FULL VERSION