MySQL系列(17): EXPLAIN输出信息之 Extra 字段解释
MySQL 查询执许计划 EXPLAIN 输出的信息有个扩展信息字段 Extra,该字段包含了有关 MySQL 如何解析查询的其他信息,可以更好地帮助理解执行计划。
该字段常见的值有 Using index、Using where。若想尽可能提高查询效率,需要关注 Using filesort 和 Using temporary 值,该值会影响查询的性能。
EXPLAIN Extra信息
此列的值有以下种可能:
- Child of ‘table’ pushed join@1 (JSON: message text) 
 This table is referenced as the child of table in a join that can be pushed down to the NDB kernel. (此表在联接中作为子表被引用…….)
- const row not found (JSON property: const_row_not_found) 
 例如出现 SELECT … FROM tbl_name 之类的查询,但表是空的。
- 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 (和 system) 表,并且注意到 WHERE 子句一直为 false。
- LooseScan(m..n) (JSON property: message) 
 使用半联接 LooseScan 策略。m 和 n 是 key 的编号。
- No matching min/max row (JSON property: message) 
 没有行满足条件查询,如 SELECT MIN(…) FROM … WHERE condition。
- no matching row in const table (JSON property: message) 
 对于具有联接的查询,有一个空表或没有满足唯一索引条件的行的表会出现该值。
- No matching rows after partition pruning (JSON property: message) 
 对于 DELETE 和 UPDATE ,优化器在分区修剪(精简)之后找不到要删除或更新的内容。与 SELECT 语句的 Impossible WHERE 的含义相似。
- No tables used (JSON property: message) 
 查询没有 FROM 子句,或者使用 FROM DUAL 子句。
 对于 INSERT 或 FRPLACE 语句,EXPLAIN 在没有 SELECT 部分时显示该值。
 例如,出现在 EXPLAIN INSERT INTO t VALUES(10) 中,该语句等同于 EXPLAIN INSERT INTO t SELECT 10 FROM DUAL.
- Not exists (JSON property: message) 
 MySQL 能够对查询执行 LEFT JOIN 优化,并且在找到与 LEFT JOIN 条件匹配的行后,不会检查此表中其它的行。如下示例:- 1 - SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL; - 假设 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 会出现该值。
- Range checked for each record (index map: N) (JSON property: message) 
 MySQL 没有找到可用的好索引,但发现前面表中的列值是已知后,可能会使用某些索引。
 对于前面的表行,MySQL 检查是否可以使用 range 或 index_merge 访问方法业检索行,这不是很快,但比没有索引的联接快。
- Scanned N databases (JSON property: message) 
 表示在处理 INFORMATION_SCHEMA 表的查询时,服务器执行的目录扫描数。N 的值可以是0,1 或 ALL。
- Select tables optimized away (JSON property: message) 
 优化器确定:1.最多只返回一行,2.若要生成此行,必须读取确定的行。在优化阶段(例如,通过读取索引行)可以获得要读取的行时,查询执行期间不需要读取任何表。
 当隐式分组查询(包含聚合函数,但不包含 group by 子句)时,将满足第一个条件。当每使用一个索引执行一行查找时,就满足了第二个条件。读取的索引数决定了要读取的行数。- 隐式分组查询示例: - 1 - SELECT MIN(c1), MIN(c2) FROM t1; - c1 和 c2 都是索引列,并且该列是索引的第一列。可以通过读取一个索引行来检索 MIN(c1) ,并且通过从不同的索引中读取一行来检索 MIN(c2) 。本例中,返回的一行数据,是由读取两个确定性行生成的。 
 如果读取的行不是确定的,则 Extra 不会显示此值,如下示例:- 1 - SELECT MIN(c2) FROM t1 WHERE c1 <= 10; 
- Skip_open_table, Open_frm_only, Open_full_table (JSON property: message) 
 这此值表示适用于 INFORMATION_SCHEMA 表的查询的文件打开优化。- Skip_open_table:不需要打开表文件。通过扫描数据库目录,该信息已在查询中可用。
- Open_frm_only:只需打开表的 .frm 文件。
- Open_full_table:未经优化的信息查找。必须打开 .frm,.MYD 和 .MYI文件。
 
- Start temporary, End temporary (JSON property: message) 
 临时表用于半联接 Duplicate Weedout 策略。
- unique row not found (JSON property: message) 
 对于 SELECT …. FROM tbl_name 之类的查询,没有行满足表上 UNIQUE 索引 或 PRIMARY KEY 的条件。
- Using filesort (JSON property: using_filesort) 
 MySQL 必须执行额外的操作,以了解如何按排序顺序检索行。
 排序是根据联接类型遍历所有行,并为所有与 WHERE 子句匹配的行存储排序的 key 和 指向行的指针;然后对 key 进行排序,并按排序顺序检索行。
- Using index (JSON property: using_index) 
 仅使用索引树中的信息从表中检索列信息。当查询公使用单个索引列时,显示此策略。
 对于具有用户定义的聚簇索引的 InnoDB 表,即使 Extra 列中不存在使用索引,实际也是可以使用索引。如果 type 是 index 并且 key 是 PRIMARY,则会出现此情况,即使用主键查询。
- Using index condition (JSON property: using_index_condition) 
 通过访问索引元组并首先测试它他来读取表,以确定是否读取全表的行。
- Using index for group-by (JSON property: using_index_for_group_by) 
 与 Using index 表访问方式相似。Using index for group-by 表示MySQL找到了一个索引,可用于检索 GROUP BY 或 DISTINCT 查询所有的列,而无需对实际的表进行任何额外的磁盘访问。
 此外,索引以最有效的方式使用,因此,对每个 group, 只需读取少数的索引。
- Using join buffer (Block Nested Loop), Using join buffer (Batched Key Access) (JSON property: using_join_buffer) 
 将早期联接中的表部分读入联接缓冲区,然后从缓冲区中使用他们的行来执行与当前表的联接。
 也就是说,将缓冲 explain 输出前一行上表中的 key,并从使用 join buffer 的行指向的表中分批提取匹配的行。
- Using MRR (JSON property: message) 
 使用 Multi-Range Read 优化策略读取表。
- Using sort_union(…), Using union(…), Using intersect(…) (JSON property: message) 
 这些指示的特定算法,显示了如何为 index_merge 联接类型合并索引扫描。
- Using temporary (JSON property: using_temporary_table) 
 要对查询进行解析,MySQL 需要创建一个临时表来保存结果。如果查询包含多个不同列的 GROUP BY 和ORDER BY 子句,则通常会发生此情况。
- Using where (JSON property: attached_condition) 
 WHERE 子句用于限制那些行与下一个表匹配或发送到客户端。
 除非特意要检索表中的所有行,否则若 Extra 值不是 Using where 并且表联接是 ALL 或 index,则可能出错了。
- Using where with pushed condition (JSON property: message) 
 此项只适用于 NDB 表。意思是 NDB Cluster 正在使用下推优化来提高非索引列和常量之间直接比较的效率。
- Zero limit (JSON property: message) 
 该查询具有 LIMIT 0 子句,并且无法选择任何行。
MySQL系列(17): EXPLAIN输出信息之 Extra 字段解释
http://blog.gxitsky.com/2019/03/15/MySQL-17-Optimizing-Explain-output-Extra/

