EXPLAIN语句提供有关MySQL如何执行语句的信息。EXPLAIN适用于SELECT、DELETE、INSERT、REPLACE和UPDATE语句。
EXPLAIN为SELECT语句中使用的每个表返回一行信息。它按照MySQL在处理语句时读取表的顺序在输出中列出表。MySQL使用嵌套循环连接方法解析所有连接。这意味着MySQL从第一个表中读取一行,然后在第二个表、第三个表等中找到匹配的行。当处理完所有表后,MySQL会输出所选列并在表列表中回溯,直到找到有更多匹配行的表。从该表中读取下一行,并继续处理下一个表。
EXPLAIN输出包括分区信息。此外,对于SELECT语句,EXPLAIN会生成扩展信息,这些信息可以在EXPLAIN之后显示为SHOW WARNINGS(见第8.8.3节,“扩展的EXPLAIN输出格式”)。
注:
在较旧的MySQL版本中,分区和扩展信息是使用EXPLAIN PARTITIONS和EXPLAIN extended生成的。这些语法仍然被认为具有向后兼容性,但默认情况下分区和扩展输出现在已启用,因此PARTITIONS和extended关键字是多余的,并且已被弃用。使用它们会导致警告;预计在未来的MySQL版本中,它们将从EXPLAIN语法中删除。
不能在同一EXPLAIN语句中同时使用弃用的PARTITIONS和EXTENDED关键字。此外,这两个关键字都不能与FORMAT选项一起使用。
注:
MySQL Workbench具有可视化解释功能,可提供Explain输出的可视化表示。请参阅教程:使用Explain提高查询性能。
EXPLAIN Output Columns
本节介绍EXPLAIN生成的输出列。后面的部分提供了有关类型和额外列的更多信息。
EXPLAIN的每一行输出都提供了关于一个表的信息。每一行都包含表8.1“EXPLAIN输出列”中总结的值,并在表后进行了更详细的描述。列名显示在表的第一列中;当使用FORMAT=JSON时,第二列提供输出中显示的等效属性名。
id (JSON name: select_id)
SELECT标识符。这是查询中SELECT的序列号。如果该行引用其他行的并集结果,则该值可以为NULL。在这种情况下,表列显示了一个类似于的值,表示该行是指id值为M和N的行的并集。
select_type (JSON name: none)
SELECT的类型,可以是下表所示的任何类型。JSON格式的EXPLAIN将SELECT类型作为query_block的属性公开,除非它是SIMPLE或PRIMARY。JSON名称(如适用)也显示在表中。
DEPENDENT通常表示使用相关子查询。见第13.2.10.7节“相关子查询”。
从属子查询评估不同于无法实现的子查询评估。对于DEPENDENT SUBQUERY,对于来自其外部上下文的变量的每组不同值,子查询只会重新计算一次。
对于UNCACHEABLE SUBQUERY,会为外部上下文的每一行重新评估子查询。
子查询的可缓存性不同于查询缓存中查询结果的缓存(如第8.10.3.1节“查询缓存的操作方式”所述)。子查询缓存发生在查询执行期间,而查询缓存仅用于在查询执行完成后存储结果。
当您使用EXPLAIN指定FORMAT=JSON时,输出没有直接等效于select_type的单个属性;query_block属性对应于给定的SELECT。与刚才显示的大多数SELECT子查询类型等效的属性是可用的(一个例子是materialized_from_subquery for materialized),并在适当的时候显示。SIMPLE或PRIMARY没有JSON等价物。
非select语句的select_type值显示受影响表的语句类型。例如,对于DELETE语句,select_type是DELETE。
table (JSON name: table_name)
输出行所引用的表的名称。这也可以是以下值之一:
unionM,N:该行是指id值为M和N的行的并集。
derivedN:该行引用id值为N的行的派生表结果。例如,派生表可能来自from子句中的子查询。
subcyN:该行是指id值为N的行的物化子查询的结果。请参阅第8.2.2.2节“使用物化优化子查询”。
partitions (JSON name: partitions)
查询将从中匹配记录的分区。对于非分区表,该值为NULL。请参阅第22.3.5节“获取分区信息”。
type (JSON name: access_type)
连接类型。有关不同类型的描述,请参阅EXPLAIN连接类型。
possible_keys (JSON name: possible_keys)
possible_keys列表示MySQL可以从中选择查找此表中行的索引。请注意,此列完全独立于EXPLAIN输出中显示的表的顺序。这意味着possible_key中的一些键在实际中可能无法用于生成的表顺序。
如果此列为NULL(或在JSON格式的输出中未定义),则没有相关索引。在这种情况下,您可以通过检查WHERE子句来检查它是否引用了适合索引的一个或多个列,从而提高查询的性能。如果是这样,请创建一个适当的索引,并再次使用EXPLAIN检查查询。请参阅第13.1.8节“ALTER TABLE语句”。
要查看表具有哪些索引,请使用SHOW INDEX FROM tbl_name。
key (JSON name: key)
key列表示MySQL实际决定使用的键(索引)。如果MySQL决定使用一个可能的_keys索引来查找行,则该索引将作为键值列出。
key可以命名一个不在possible_keys值中的索引。如果所有可能的_keys索引都不适合查找行,但查询选择的所有列都是其他索引的列,则可能会发生这种情况。也就是说,命名索引覆盖了选定的列,因此尽管它不用于确定要检索哪些行,但索引扫描比数据行扫描更有效。
对于InnoDB,即使查询也选择了主键,辅助索引也可能覆盖所选列,因为InnoDB将主键值与每个辅助索引一起存储。如果键为NULL,MySQL找不到用于更有效地执行查询的索引。
要强制MySQL使用或忽略possible_keys列中列出的索引,请在查询中使用force index、use index或ignore index。见第8.9.4节“索引提示”。
对于MyISAM表,运行ANALYZE TABLE有助于优化器选择更好的索引。对于MyISAM表,myisamck-analyze也会执行相同的操作。见第13.7.2.1节“分析表声明”和第7.6节“MyISAM表维护和故障恢复”。
key_len (JSON name: key_length)
key_len列表示MySQL决定使用的密钥的长度。key_len的值使您能够确定MySQL实际使用的多部分密钥的多少部分。如果键列显示NULL,则key_len列也显示NULL。
由于密钥存储格式的原因,对于可以为NULL的列,密钥长度比NOT NULL列长一个。
ref (JSON name: ref)
ref列显示了将哪些列或常量与键列中指定的索引进行比较,以从表中选择行。
如果值是func,则使用的值是某个函数的结果。要查看哪个函数,请使用EXPLAIN后的SHOW WARNINGS查看扩展的EXPLAIN输出。该函数实际上可能是一个运算符,如算术运算符。
rows (JSON name: rows)
行列表示MySQL认为执行查询必须检查的行数。
对于InnoDB表,这个数字是一个估计值,可能并不总是准确的。
filtered (JSON name: filtered)
筛选列表示按表条件筛选的表行的估计百分比。最大值为100,这意味着没有对行进行过滤。从100开始递减的值表示过滤量增加。行显示了检查的估计行数,行×过滤显示了与下表连接的行数。例如,如果行数为1000,过滤后的行数为50.00(50%),则要与下表连接的行数是1000×50%=500。
Extra (JSON name: none)
此列包含有关MySQL如何解析查询的其他信息。有关不同值的描述,请参阅EXPLAIN附加信息。
Extra列没有对应的单个JSON属性;但是,此列中可能出现的值将作为JSON属性或消息属性的文本公开。