MySQL系列(17): EXPLAIN输出信息之 Extra 字段解释

  MySQL 查询执许计划 EXPLAIN 输出的信息有个扩展信息字段 Extra,该字段包含了有关 MySQL 如何解析查询的其他信息,可以更好地帮助理解执行计划。

  该字段常见的值有 Using index、Using where。若想尽可能提高查询效率,需要关注 Using filesort 和 Using temporary 值,该值会影响查询的性能。

EXPLAIN Extra信息

此列的值有以下种可能:

  1. 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. (此表在联接中作为子表被引用…….)

  2. const row not found (JSON property: const_row_not_found)
    例如出现 SELECT … FROM tbl_name 之类的查询,但表是空的。

  3. Deleting all rows (JSON property: message)
    对于 DELETE ,某些存储引擎(如 MyISAM)提供了一种可以简单快捷删除所有表行的方法。如果引擎使用此方法估化,则会显示该值。

  4. Distinct (JSON property: distinct)
    MySQL 查找没有重复的值,在找到第一个匹配行后就会停止搜索更多的行。

  5. FirstMatch(tbl_name) (JSON property: first_match)
    为 tbl_name 表使用半联接 FirstMatch 联接快捷方式策略。

  6. Full scan on NULL key (JSON property: message)
    当优化器无法使用索引查找访问方法时,子查询优化作为回退策略会出现该值。

  7. Impossible HAVING (JSON property: message)
    HAVING 子句一直是 false 并且无法选择任何行。

  8. Impossible WHERE (JSON property: message)
    WHERE 子句一直是 false 并且无法选择任何行。

  9. Impossible WHERE noticed after reading const tables (JSON property: message)
    MySQL 已经读取了所有 const (和 system) 表,并且注意到 WHERE 子句一直为 false。

  10. LooseScan(m..n) (JSON property: message)
    使用半联接 LooseScan 策略。m 和 n 是 key 的编号。

  11. No matching min/max row (JSON property: message)
    没有行满足条件查询,如 SELECT MIN(…) FROM … WHERE condition。

  12. no matching row in const table (JSON property: message)
    对于具有联接的查询,有一个空表或没有满足唯一索引条件的行的表会出现该值。

  13. No matching rows after partition pruning (JSON property: message)
    对于 DELETE 和 UPDATE ,优化器在分区修剪(精简)之后找不到要删除或更新的内容。与 SELECT 语句的 Impossible WHERE 的含义相似。

  14. 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.

  15. 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 中实际匹配多少行。

  16. Plan isn’t ready yet (JSON property: none)
    执行计划还没还没创建完成。当优化器尚未完成为联接中的扫许语句创建执行计划时,EXPLAIN FOR CONNECTION 会出现该值。

  17. Range checked for each record (index map: N) (JSON property: message)
    MySQL 没有找到可用的好索引,但发现前面表中的列值是已知后,可能会使用某些索引。
    对于前面的表行,MySQL 检查是否可以使用 range 或 index_merge 访问方法业检索行,这不是很快,但比没有索引的联接快。

  18. Scanned N databases (JSON property: message)
    表示在处理 INFORMATION_SCHEMA 表的查询时,服务器执行的目录扫描数。N 的值可以是0,1 或 ALL。

  19. 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;
  20. 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文件。
  21. Start temporary, End temporary (JSON property: message)
    临时表用于半联接 Duplicate Weedout 策略。

  22. unique row not found (JSON property: message)
    对于 SELECT …. FROM tbl_name 之类的查询,没有行满足表上 UNIQUE 索引 或 PRIMARY KEY 的条件。

  23. Using filesort (JSON property: using_filesort)
    MySQL 必须执行额外的操作,以了解如何按排序顺序检索行。
    排序是根据联接类型遍历所有行,并为所有与 WHERE 子句匹配的行存储排序的 key 和 指向行的指针;然后对 key 进行排序,并按排序顺序检索行。

  24. Using index (JSON property: using_index)
    仅使用索引树中的信息从表中检索列信息。当查询公使用单个索引列时,显示此策略。
    对于具有用户定义的聚簇索引的 InnoDB 表,即使 Extra 列中不存在使用索引,实际也是可以使用索引。如果 type 是 index 并且 key 是 PRIMARY,则会出现此情况,即使用主键查询。

  25. Using index condition (JSON property: using_index_condition)
    通过访问索引元组并首先测试它他来读取表,以确定是否读取全表的行。

  26. Using index for group-by (JSON property: using_index_for_group_by)
    与 Using index 表访问方式相似。Using index for group-by 表示MySQL找到了一个索引,可用于检索 GROUP BY 或 DISTINCT 查询所有的列,而无需对实际的表进行任何额外的磁盘访问。
    此外,索引以最有效的方式使用,因此,对每个 group, 只需读取少数的索引。

  27. Using join buffer (Block Nested Loop), Using join buffer (Batched Key Access) (JSON property: using_join_buffer)
    将早期联接中的表部分读入联接缓冲区,然后从缓冲区中使用他们的行来执行与当前表的联接。
    也就是说,将缓冲 explain 输出前一行上表中的 key,并从使用 join buffer 的行指向的表中分批提取匹配的行。

  28. Using MRR (JSON property: message)
    使用 Multi-Range Read 优化策略读取表。

  29. Using sort_union(…), Using union(…), Using intersect(…) (JSON property: message)
    这些指示的特定算法,显示了如何为 index_merge 联接类型合并索引扫描。

  30. Using temporary (JSON property: using_temporary_table)
    要对查询进行解析,MySQL 需要创建一个临时表来保存结果。如果查询包含多个不同列的 GROUP BY 和ORDER BY 子句,则通常会发生此情况。

  31. Using where (JSON property: attached_condition)
    WHERE 子句用于限制那些行与下一个表匹配或发送到客户端。
    除非特意要检索表中的所有行,否则若 Extra 值不是 Using where 并且表联接是 ALL 或 index,则可能出错了。

  32. Using where with pushed condition (JSON property: message)
    此项只适用于 NDB 表。意思是 NDB Cluster 正在使用下推优化来提高非索引列和常量之间直接比较的效率。

  33. Zero limit (JSON property: message)
    该查询具有 LIMIT 0 子句,并且无法选择任何行。

MySQL系列(17): EXPLAIN输出信息之 Extra 字段解释

http://blog.gxitsky.com/2019/03/15/MySQL-17-Optimizing-Explain-output-Extra/

作者

光星

发布于

2019-03-15

更新于

2023-03-06

许可协议

评论