使用 EXPLAIN 解读执行计划
SQL 是一种声明性语言,因此无法通过 SQL 语句直接判断一条查询的执行是否有效率,但是可以使用 EXPLAIN 语句查看当前的执行计划。
示例
我们这里准备一个简单的示例,帮助你理解使用 EXPLAIN 解读执行计划。
1. > drop table if exists a;
2. > create table a(a int);
3. > insert into a values(1),(2),(3),(4),(5),(6),(7),(8);
4. > select count(*) from a where a>=2 and a<=8;
5. +----------+
6. | count(*) |
7. +----------+
8. | 7 |
9. +----------+
10. 1 row in set (0.00 sec)
12. > explain select count(*) from a where a>=2 and a<=8;
13. +-----------------------------------------------------------------------------------+
14. | QUERY PLAN |
15. +-----------------------------------------------------------------------------------+
16. | Project |
17. | -> Aggregate |
18. | Aggregate Functions: starcount(1) |
19. | -> Table Scan on aab.a |
20. | Filter Cond: (CAST(a.a AS BIGINT) >= 2), (CAST(a.a AS BIGINT) <= 8) |
21. +-----------------------------------------------------------------------------------+
22. 5 rows in set (0.00 sec)
以上是该查询的执行计划结果。从 Filter Cond 算子开始向上看,查询的执行过程如下:
- 先执行过滤条件
Filter Cond:即过滤出数据类型为BIGINT且大于等于 2,小于等于 8 的整数,按照计算推理,应该为(2),(3),(4),(5),(6),(7),(8)。 - 扫描数据库 aab 中的表 a。
- 聚合计算满足条件整数的个数,为 7 个。
最终,得到查询结果为 7,即 count(*) = 7。
评估当前的性能
EXPLAIN 语句只返回查询的执行计划,并不执行该查询。若要获取实际的执行时间,可执行该查询,或使用 EXPLAIN ANALYZE 语句。
什么是 EXPLAIN ANALYZE
EXPLAIN ANALYZE 是一个用于查询的分析工具,它将向你显示 SQL 在查询上花费的时间以及原因。它将计划查询、检测它并执行它,同时计算行数并测量在执行计划的各个点花费的时间。执行完成后,EXPLAIN ANALYZE 将打印计划和测量结果,而不是查询结果。
除了正常 EXPLAIN 将打印的查询计划和估计成本之外,EXPLAIN ANALYZE 还打印执行计划中各个迭代器的实际成本。
如何使用它?
这里还是继续使用上述示例,你可以执行下面的代码:
1. > explain analyze select count(*) from a where a>=2 and a<=8;
2. +-------------------------------------------------------------------------------------------------------------------------------+
3. | QUERY PLAN |
4. +-------------------------------------------------------------------------------------------------------------------------------+
5. | Project |
6. | Analyze: timeConsumed=0us inputRows=1 outputRows=1 inputSize=8bytes outputSize=8bytes memorySize=8bytes |
7. | -> Aggregate |
8. | Analyze: timeConsumed=3317us inputRows=2 outputRows=2 inputSize=8bytes outputSize=16bytes memorySize=16bytes |
9. | Aggregate Functions: starcount(1) |
10. | -> Table Scan on aab.a |
11. | Analyze: timeConsumed=6643us inputRows=31 outputRows=24 inputSize=96bytes outputSize=64bytes memorySize=64bytes |
12. | Filter Cond: (CAST(a.a AS BIGINT) >= 2), (CAST(a.a AS BIGINT) <= 8) |
13. +-------------------------------------------------------------------------------------------------------------------------------+
14. 8 rows in set (0.00 sec)
从打印的执行结果来看,当分别执行聚合计算和扫描表时,都会得出以下几个测量值,这些测量值可以作为参考项:
- 总耗时 timeConsumed
- 读取的行数
- 读取的容量大小
- 内存大小
通过在这些信息,你可以分析查询并理解它们为何是这样的表现,可以从以下几个方面进行探索:
- 执行这些查询,需要花费多久?你可以查看总耗时。
- 为什么执行当前的查询计划,而不是其他的执行计划?你可以查看行计数器。当估计行数与实际行数之间的巨大差异(即,几个数量级或更多)时,说明优化器根据估计选择计划,但查看实际执行可以方便你得知到底哪个执行计划更好。
所以使用 EXPLAIN ANALYZE 就是分析查询执行。
从上面的输出结果来看,执行以上示例查询耗时 0.00 秒,说明执行性能较为理想。也由于我们这次示例中执行的查询简单,满足较高的执行性能。
更多关于 EXPLAIN ANALYZE 的信息,请参见 EXPLAIN ANALYZE。
