查询性能分析器(EXPLAIN ANALYZE)

Exisi 2023-04-26 12:14:20
Categories: Tags:
  • MySQL 8.0.18 引入了 EXPLAIN ANALYZE,它运行一个语句并生成 EXPLAIN 输出,同时提供时间和基于迭代器的额外信息,说明优化器的期望如何匹配实际执行。对于每个迭代器,包含以下信息:

 

  • 预计执行成本(有些迭代器没有被成本模型考虑在内,因此不包括在估计中。)
  • 返回的估计行数
  • 返回第一行的时间
  • 执行此迭代器(包括子迭代器,但不包括父迭代器)所花费的时间,以毫秒为单位。(当有多个循环时,此图显示每个循环的平均时间。)
  • 迭代器返回的行数
  • 循环次数

 

  • EXPLAIN ANALYZE 向用户显示 MySQL 在查询上花费的时间以及原因。它将产生查询计划,并对其进行检测和执行,同时计算行数并度量执行计划中不同点上花费的时间,然后输出执行计划中各个迭代器的实际成本。执行完成后,EXPLAIN ANALYZE 将输出计划和度量结果,而不是查询结果。

 

  • EXPLAIN ANALYZE 可以与 SELECT 语句以及多表 UPDATE DELETE 语句一起使用。从MySQL 8.0.19开始,它也可以与 TABLE 语句一起使用

 

{EXPLAIN | DESCRIBE | DESC}

ANALYZE [FORMAT = TREE] select_statement;

 

参数

描述

select_statement

查询语句

示例

EXPLAIN ANALYZE

SELECT * FROM t1 JOIN t2 ON (t1.c1 = t2.c2);

 

运行结果如下:

*************************** 1. row ***************************
EXPLAIN: -> Inner hash join (t2.c2 = t1.c1)  (cost=4.70 rows=6)
(actual time=0.032..0.035 rows=6 loops=1)
    -> Table scan on t2  (cost=0.06 rows=6)
(actual time=0.003..0.005 rows=6 loops=1)
    -> Hash
        -> Table scan on t1  (cost=0.85 rows=6)
(actual time=0.018..0.022 rows=6 loops=1)

示例

EXPLAIN ANALYZE

SELECT * FROM t3 WHERE i > 8

 

运行结果如下:

*************************** 1. row ***************************
EXPLAIN: -> Filter: (t3.i > 8)  (cost=1.75 rows=5)
(actual time=0.019..0.021 rows=6 loops=1)
    -> Table scan on t3  (cost=1.75 rows=15)
(actual time=0.017..0.019 rows=15 loops=1)

示例

EXPLAIN ANALYZE

SELECT * FROM t3 WHERE pk > 17;

 

运行结果如下:

*************************** 1. row ***************************
EXPLAIN: -> Filter: (t3.pk > 17)  (cost=1.26 rows=5)
(actual time=0.013..0.016 rows=5 loops=1)
    -> Index range scan on t3 using PRIMARY  (cost=1.26 rows=5)
(actual time=0.012..0.014 rows=5 loops=1)

示例

EXPLAIN ANALYZE

SELECT * FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2 WHERE id < 10)

 

运行结果如下:

*************************** 1. row ***************************
  -> Nested loop inner join  (cost=4.95 rows=9) (actual time=0.153..0.200 rows=9 loops=1)
    -> Filter: (`<subquery2>`.b is not null)  (cost=2.83..1.80 rows=9) (actual time=0.097..0.100 rows=9 loops=1)
        -> Table scan on <subquery2>  (cost=0.29..2.61 rows=9) (actual time=0.001..0.002 rows=9 loops=1)
            -> Materialize with deduplication  (cost=3.25..5.58 rows=9) (actual time=0.090..0.092 rows=9 loops=1)
                -> Filter: (t2.b is not null)  (cost=2.06 rows=9) (actual time=0.037..0.042 rows=9 loops=1)
                    -> Filter: (t2.id < 10)  (cost=2.06 rows=9) (actual time=0.036..0.040 rows=9 loops=1)
                        -> Index range scan on t2 using PRIMARY  (cost=2.06 rows=9) (actual time=0.035..0.038 rows=9 loops=1)
    -> Index lookup on t1 using a (a=`<subquery2>`.b)  (cost=2.35 rows=1) (actual time=0.010..0.010 rows=1 loops=9)
1 row in set (0.01 sec)

 

  • 嵌套查询(Nested loop)查询计划的解读顺序从最内部开始,然后回到最外层从上到下执行

 

 

  • 查询执行信息使用 TREE 输出格式显示,其中节点代表迭代器。 EXPLAIN ANALYZE 始终使用 TREE 输出格式。

 

  • MySQL 8.0.21 及更高版本中,EXPLAIN ANALYZE  可以选择使用 FORMAT=TREE 明确指定; TREE 以外的格式仍然不受支持,也就是说 FORMAT=TRADITIONAL FORMAT=JSON 都会引发错误。同时 explain_format 系统变量如果值为 JSON TRADITIONAL ,也将返回错误,除非 FORMAT=TREE 被指定为语句的一部分。

 

  • MySQL 8.0.20 开始,可以使用 KILL QUERY CTRL+C 终止此语句。

 

  • EXPLAIN ANALYZE 不能与 FOR CONNECTION 一起使用。

 

 

来自 <https://dev.mysql.com/doc/refman/8.0/en/explain.html>