EXPLAIN Output Format
EXPLAIN Extra Information
EXPLAIN输出的Extra列包含有关MySQL如何解析查询的其他信息。以下列表解释了此列中可能出现的值。每个项目还指示JSON格式输出的哪个属性显示Extra值。对于其中一些,有一个特定的属性。其他则显示为消息属性的文本。
如果你想让查询尽可能快,请注意Using filesort和Using temporary的额外列值,或者在JSON格式的EXPLAIN输出中,注意Using _filesort和Using _temporary_table属性等于true。
Child of 'table' pushed join@1 (JSON: message text)
此表在可以下推到NDB内核的联接中被引用为表的子表。仅在启用下推连接时适用于NDB群集。有关更多信息和示例,请参阅ndb_join_pushdown服务器系统变量的描述。
const row not found (JSON property: const_row_not_found)
For a query such as SELECT ... FROM tbl_name, the table was empty.
Deleting all rows (JSON property: message)
对于DELETE,一些存储引擎(如MyISAM)支持以简单快速的方式删除所有表行的处理程序方法。如果发动机使用此优化,则显示此额外值。
Distinct (JSON property: distinct)
MySQL正在寻找不同的值,因此在找到第一个匹配的行后,它停止为当前行组合搜索更多行。
FirstMatch(tbl_name) (JSON property: first_match)
tbl_name使用半连接FirstMatch连接快捷策略。
Full scan on NULL key (JSON property: message)
当优化器无法使用索引查找访问方法时,作为回退策略的子查询优化会发生这种情况。
Impossible HAVING (JSON property: message)
HAVING子句始终为false,不能选择任何行。
Impossible WHERE (JSON property: message)
WHERE子句始终为false,不能选择任何行。
Impossible WHERE noticed after reading const tables (JSON property: message)
MySQL已经读取了所有const(和系统)表,并注意到WHERE子句始终为false。
LooseScan(m..n) (JSON property: message)
The semijoin LooseScan strategy is used. m and n are key part numbers.
No matching min/max row (JSON property: message)
No row satisfies the condition for a query such as SELECT MIN(...) FROM ... WHERE condition.
no matching row in const table (JSON property: message)
For a query with a join, there was an empty table or a table with no rows satisfying a unique index condition.
No matching rows after partition pruning (JSON property: message)
对于DELETE或UPDATE,优化器在分区修剪后没有发现任何要删除或更新的内容。它的含义类似于SELECT语句的Impossible WHERE。
No tables used (JSON property: message)
查询没有FROM子句,或者有FROM DUAL子句。
对于INSERT或REPLACE语句,当没有SELECT部分时,EXPLAIN会显示此值。例如,它出现在EXPLAIN INSERT INTO t VALUES(10)中,因为这相当于EXPLAIN INSERT INTO t SELECT 10 FROM DUAL。
Not exists (JSON property: message)
MySQL能够对查询进行LEFT JOIN优化,并且在找到一行符合LEFT JOIN条件后,不会检查此表中前一行组合的更多行。以下是可以通过这种方式优化的查询类型的示例:
假设t2.id被定义为NOT NULL。在这种情况下,MySQL扫描t1,并使用t1.id的值查找t2中的行。如果MySQL在t2中找到匹配的行,它就知道t2.id永远不会为NULL,并且不会扫描t2中具有相同id值的其余行。换句话说,对于t1中的每一行,MySQL只需要在t2中进行一次查找,而不管t2中实际匹配的行数是多少。
Plan isn't ready yet (JSON property: none)
当优化器尚未完成为在指定连接中执行的语句创建执行计划时,此值将与EXPLAIN FOR CONNECTION一起出现。如果执行计划输出包含多行,则根据优化器确定完整执行计划的进度,其中任何一行或所有行都可能具有此Extra值。
Range checked for each record (index map: N) (JSON property: message)
MySQL发现没有好的索引可供使用,但发现在已知前面表中的列值后,可能会使用一些索引。对于前面表中的每一行组合,MySQL都会检查是否可以使用range或index_merge访问方法来检索行。这不是很快,但比在没有索引的情况下执行连接要快。适用性标准如第8.2.1.2节“范围优化”和第8.2.1.3节“索引合并优化”所述,但上表的所有列值都是已知的,并且被视为常数。
索引从1开始编号,顺序与表中的SHOW INDEX所示的顺序相同。索引映射值N是指示哪些索引是候选的位掩码值。例如,值0x19(二进制11001)表示考虑索引1、4和5。
Scanned N databases (JSON property: message)
这表示服务器在处理对INFORMATION_SCHEMA表的查询时执行的目录扫描次数,如第8.2.3节“优化INFORMATY_SCHEMA查询”所述。N的值可以是0、1或全部。
Select tables optimized away (JSON property: message)
优化器确定1)最多应返回一行,2)要生成此行,必须读取一组确定性的行。当在优化阶段可以读取要读取的行时(例如,通过读取索引行),在查询执行期间不需要读取任何表。
当查询隐式分组时(包含聚合函数但没有GROUP BY子句),满足第一个条件。当对每个使用的索引执行一行查找时,满足第二个条件。读取的索引数量决定了要读取的行数。
考虑以下隐式分组查询:
假设MIN(c1)可以通过读取一个索引行来检索,MIN(c2)可以通过从不同的索引读取一行来检索。也就是说,对于每一列c1和c2,都存在一个索引,其中该列是索引的第一列。在这种情况下,返回一行,这是通过读取两个确定性行产生的。
如果要读取的行不是确定性的,则不会出现此Extra值。考虑以下查询:
假设(c1,c2)是一个覆盖指数。使用此索引,必须扫描c1<=10的所有行以找到最小c2值。相比之下,考虑一下这个查询:
在这种情况下,c1=10的第一索引行包含最小c2值。只需读取一行即可生成返回的行。
对于每个表保持精确行数的存储引擎(如MyISAM,但不包括InnoDB),对于缺少WHERE子句或始终为真且没有GROUP BY子句的count(*)查询,可能会出现此Extra值。(这是隐式分组查询的一个实例,其中存储引擎影响是否可以读取确定数量的行。)
Skip_open_table, Open_frm_only, Open_full_table (JSON property: message)
这些值表示应用于对INFORMATION_SCHEMA表的查询的文件打开优化,如第8.2.3节“优化INFORMATER_SCHEMA查询”所述。
Start temporary, End temporary (JSON property: message)
This indicates temporary table use for the semijoin Duplicate Weedout strategy. 这表示临时表用于半连接重复淘汰策略。
unique row not found (JSON property: message)
For a query such as SELECT ... FROM tbl_name, no rows satisfy the condition for a UNIQUE index or PRIMARY KEY on the table.
Using filesort (JSON property: using_filesort)
MySQL必须进行额外的传递,以了解如何按排序顺序检索行。排序是通过根据连接类型遍历所有行,并存储与WHERE子句匹配的所有行的排序键和指向该行的指针来完成的。然后对键进行排序,并按排序顺序检索行。见第8.2.1.14节“按优化排序”。
Using index (JSON property: using_index)
仅使用索引树中的信息从表中检索列信息,而不必进行额外的查找来读取实际行。当查询仅使用属于单个索引的列时,可以使用此策略。
对于具有用户定义聚集索引的InnoDB表,即使Extra列中没有Using index,也可以使用该索引。如果类型是索引,键是PRIMARY,则会出现这种情况。
Using index condition (JSON property: using_index_condition)
通过访问索引元组并首先测试它们来确定是否读取整个表行,从而读取表。这样,索引信息用于延迟(“向下推”)读取整个表行,除非有必要。见第8.2.1.5节“指标条件下推优化”。
Using index for group-by (JSON property: using_index_for_group_by)
与Using index表访问方法类似,Using index for group by表示MySQL找到了一个索引,该索引可用于检索group by或DISTINCT查询的所有列,而无需对实际表进行任何额外的磁盘访问。此外,索引以最有效的方式使用,因此对于每个组,只读取几个索引条目。有关详细信息,请参阅第8.2.1.15节“按优化分组”。
Using join buffer (Block Nested Loop), Using join buffer (Batched Key Access) (JSON property: using_join_buffer)
来自早期联接的表被分部分读入联接缓冲区,然后它们的行从缓冲区中用于执行与当前表的联接。(块嵌套循环)表示使用块嵌套循环算法,(批量密钥访问)表示使用批量密钥访问算法。也就是说,EXPLAIN输出前一行表中的键被缓冲,匹配的行从出现Using join buffer的行表示的表中批量提取。
在JSON格式的输出中,using _join_buffer的值始终是块嵌套循环或批处理密钥访问之一。
有关这些算法的详细信息,请参见块嵌套循环连接算法和批处理密钥访问连接。
Using MRR (JSON property: message)
使用多范围读取优化策略读取表。见第8.2.1.10节“多范围读取优化”。
Using sort_union(...), Using union(...), Using intersect(...) (JSON property: message)
这些指示了显示如何合并index_merge连接类型的索引扫描的特定算法。见第8.2.1.3节“索引合并优化”。
Using temporary (JSON property: using_temporary_table)
为了解决查询,MySQL需要创建一个临时表来保存结果。如果查询包含以不同方式列出列的GROUP BY和ORDER BY子句,则通常会发生这种情况。
Using where (JSON property: attached_condition)
WHERE子句用于限制哪些行与下一个表匹配或发送到客户端。除非您特别打算从表中获取或检查所有行,否则如果Extra值不是Using where,并且表连接类型是all或index,则查询中可能会出现问题。
在JSON格式的输出中使用where没有直接对应项;attachd_condition属性包含使用的任何WHERE条件。
Using where with pushed condition (JSON property: message)
此项仅适用于NDB表。这意味着NDB Cluster正在使用条件下推优化来提高无索引列和常数之间直接比较的效率。在这种情况下,条件被“下推”到集群的数据节点,并在所有数据节点上同时进行评估。这消除了在网络上发送不匹配行的需要,并且在可以但不使用条件推送的情况下,可以将此类查询的速度提高5到10倍。有关更多信息,请参阅第8.2.1.4节“发动机状态下推压优化”。
Zero limit (JSON property: message)
The query had a LIMIT 0 clause and cannot select any rows.