本文详细介绍 MySQL 数据库的 EXPLAIN 语句,旨在帮助 MySQL 开发人员更好的通过 EXPLAIN 语句分析 Sql 语句的执行计划。如有不正之处,欢迎批评指正。
为了保证内容的权威性,我选择了翻译 Mysql5.7 官方文档8.8.2 EXPLAIN Output Format 章节的内容。
英文地址:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
翻译内容如下:
EXPLAIN 语句提供关于 MySQL 执行语句的信息。它同 SELECT、DELETE、INSERT、REPLACE、UPDATE语句一起使用,如:EXPLAIN SELECT * FROM TABLE。
EXPLAIN 为 SELECT 语句中使用到的每个表返回一行信息。它在输出中按照MySQL在处理语句时读取它们的顺序列出这些表。MySQL 使用 nested-loop join 解析所有的连接(joins)。这意味着 MySQL 从第一个表中读取一行记录,然后在第二个表、第三个表查找匹配行,以此类推。当所有的表被处理完成后, MySQL 输出选中的列,并且通过表数据(the table list)回溯有更多匹配行的表。从这个表中读取下一行数据,继续通过后续表进行行匹配。
EXPLAIN 语句的输出包括分区信息。同时,EXPLAIN 语句为 SELECT 语句生成扩展信息,并且随着 EXPLAIN 的SHOW WARNINGS 一起显示(见8.8.3 Extended EXPLAIN Output Format)。
注意
在旧的 MySQL 版本中,分区和扩展信息是通过 EXPLAIN PARTITIONS 和 EXPLAIN EXTENDED 语句生成的。为了向后的兼容性,这些语法还有可以使用的,但是现在分区和扩展信息的输出在默认情况下是启用的,所以 PARTITIONS 和 EXTENDED 关键词是多余的、不被推荐的。使用它们会导致一个警告,并且在 MySQL 将来的发行版本中,它们将要被从 EXPLAIN 语法中移除。
注意
MySQL Workbench 有一个可视化的解释能力,它为 EXPLAIN 语句的输出提供一个可视化的表现。见Tutorial: Using Visual Explain to Improve Query Performance。
这个章节描述 EXPLAIN 语句生成的输出列。之后的章节提供 type 和 Extra 列的附加信息。
EXPLAIN 语句的每个输出行都提供了一个表的信息。在 Table 8.1“EXPLAIN Output Columns”中总结了输出行包含的值,并加以详细的说明。表(Table 8.1)的第一列显示列名,第二列提供了等效的 JSON 属性名称,在输出格式为 JSON 时使用。
Table 8.1 EXPLAIN Output Columns
Column | JSON Name | 含义 |
---|---|---|
id | select_id | select 标识符 |
select_type | None | select 类型 |
table | table_name | 输出行描述的表的表名 |
partitions | partitions | 匹配的分区 |
type | access_type | 连接类型 |
possible_keys | possible_keys | 可供选择使用的索引 |
key | key | 实际使用的索引 |
key_len | key_length | 实际使用的索引的长度 |
ref | ref | 与索引进行比较的列,也就是关联表使用的列 |
rows | rows | 将要被检查的估算的行数 |
filtered | filtered | 被表条件过滤的行数的百分比 |
Extra | None | 附件信息 |
注意
如果 JSON 属性的值为 NULL ,在 JSON-formatted 格式的 EXPLAIN 输出中将不被显示。
id (JSON name: select_id)
SELECT 标识符,该值为 SELECT 在查询中的顺序号,如果当前行引用的是其他行的联合查询结果,该值将被设置为 NULL。在这种情况下,表中的列将显示一个类似于
的值,标识该行为 id 值为 M 和 N 的联合。
select_type (JSON name: none)
SELECT 的类型,它可以是下表中展示的任意一个值。如果该值为 SIMPLE 或者 PRIMARY,一个 JSON 格式的 EXPLAIN 将以一个 query_block 的属性显示 SELECT 的类型。JSON 的名称如下表所示。
select_type Value | JSON Name | 含义 |
---|---|---|
SIMPLE | None | 简单的 SELECT (没有使用 UNION 或者 subqueries) |
PRIMARY | None | 最外层的 SELECT |
UNION | None | 在 UNION 查询中的第二个或者之后的 SELECT 语句 |
DEPENDENT UNION | dependent (true) | 在 UNION 查询中的第二个或者之后的 SELECT 语句,依赖外层的查询 |
UNION RESULT | union_result | 联合查询的结果 |
SUBQUERY | None | 在子查询中的第一个 SELECT |
DEPENDENT SUBQUERY | dependent (true) | 在 subquery (子查询)中的第一个 SELECT,依赖于外层查询 |
DERIVED | None | 衍生的表 SELECT(由 FROM 中的 subquery 引起) |
MATERIALIZED | materialized_from_subquery | 物化子查询 |
UNCACHEABLE SUBQUERY | cacheable (false) | 子查询的结果不能被缓存,必须重新评估外部查询的每一行 |
UNCACHEABLE UNION | cacheable (false) | 在 UNION(联合查询)中的第二个或者之后的多个 select 都属于不可缓存的子查询(见 UNCACHEABLE SUBQUERY) |
依赖通常意味着一个相关子查询的使用。见Section 13.2.10.7, “Correlated Subqueries”
相关子查询的评估不同于不可缓存的子查询评估。关于相关子查询,子查询只重新评估一次外部上下文环境的每一组变量的不同值。关于不可缓存的子查询,子查询重新评估外部上下文环境的每一行数据。
子查询的缓存不同与 query cache 中查询结果的缓存(见 Section 8.10.3.1, “How the Query Cache Operates”)。子查询缓存发生在查询执行期间,而 query cache 用来存储查询执行完成后的结果。
当你为 EXPLAIN 指定了 JSON 格式,它的输出中没有单一的属性直接等同于 select_type,query_block 属性对应一个给定的 SELECT。它的属性等同于大多数的 SELECT 子查询类型,并且只显示可用的(例如 materialized_from_subquery),并在适当的时候进行显示。JSON 属性中没有与 SIMPLE 或者 PRIMARY等同的属性。
对于 non-SELECT 语句,select_type 显示受影响的表的语句的类型。例如:对于 DELETE 语句,select_type 的值为 DELETE。
:该行指的是 ID 值为 M 和 N 的行的联合。
:该行指的是衍生表结果,该结果为 ID 值为 N 的行。可能会生成一个衍生表,例如:在 FROM 语句中存在一个 from a subquery。
:该行指的是一个物化子查询的结果,该结果为 ID 值为 N 的行。见Section 8.2.2.2, “Optimizing Subqueries with Materialization”本节的内容先翻译到这里,关于连接类型、扩展信息、输出解释三部分,会在后续三篇博客中进行翻译。