简介

mysql explain(或desc)用于分析SQL语句的执行计划,多用于测试查询性能。语法:explain sql...

注意

  1. explain执行DML语句,数据不发生变化。
  2. explain执行的结果可以有多条数据,一条数据对应一个表,如果涉及union,MySQL内部会产生一个临时表,就会导致结果多一行数据。
  3. union all不会创建临时表,所以就不会有多一行的数据。

id

这是select编号,不是返回结果的自增id。
值越大优先级越高。
如果涉及多表join,id就会重复,因为就一个select。
涉及子查询,MySQL Server 优化器 可能会把子查询转化为join,所以联调select id可能都是1
涉及union,临时表的那一列,id值为null。

select_type

操作类型,包括简单表查询、联合查询、子查询等。

  • SIMPLE: 简单表查询,不包含union或者子查询。
  • PRIMARY: 主查询,复杂查询中的最外层查询,或者union中左边的表。
  • SUBQUERY: 不相关子查询
  • DEPENDENT SUBQUERY: 依赖外部查询的子查询,或者称之为相关子查询。
  • DERIVED: 派生表,从查询结果派生的临时表,from后面的子查询。
  • UNION: UNION 查询中各个子查询的操作类型。
  • UNION RESULT: UNION 查询的结果集。
  • DEPENDENT UNION: 依赖外部查询的 UNION 查询,也就是子查询中有union
  • UNCACHEABLE SUBQUERY: 无法被缓存的子查询。
  • UNCACHEABLE UNION: 无法被缓存的 UNION 查询。

table

被操作的表,用于显示被操作的对象。
实际表名:表示查询语句中直接引用的表名。

  • <derivedN>:表示派生表,它是从查询结果中派生出来的临时表,派生表的编号可能是 1、2、3 等。
  • <unionM-N>:表示 UNION 查询中的结果集,其中 M 表示结果集的编号,N 表示 UNION 查询中的子查询编号。
  • <temporary>:表示临时表,这是在查询过程中创建的临时存储表。
  • <subqueryN>:表示子查询结果,其中 N 是子查询的编号。

partitions

分析 MySQL 查询语句如何利用分区表的工具,可以查看 MySQL 执行查询时会涉及到哪些分区,以及查询优化器如何选择分区来执行查询。

type

返回在执行查询时使用的访问方法,和索引相关, 已做排序。

  • system,当使用MyiSAM或Memory引擎的表只有一条记录的时候是system,不要奢望。
  • const:使用主键索引,或唯一索引等值匹配。
  • eq_ref:使用join时,被驱动表通过主键或者唯一索引列进行等值关联的方式,例如select * from a left join b on a.id = b.id;,b是eq_ref,a是all。
  • ref: 使用非唯一索引等值匹配。
  • range:对添加过任意索引的列,进行范围匹配,<、<=、>、>=、in、between。
  • index:MySQL 使用索引来扫描整个索引树,不需要回表,通常会发生在覆盖索引的情况。
  • ALL:全表扫描。

不常见类型:

  • fulltext:全文索引。
  • ref_or_null:对二级索引进行等值匹配,并添加or = null的条件。
  • index_merge:使用了多个单列索引来执行查询。当在查询条件中存在多个列,且每个列都有单独的索引时。
  • unique_subquery:不容易遇见,in 后面跟子查询,查询优化器将in转换为exists子查询,且这些自查徐你可以使用到主键进行等值匹配才可以。如explain select * from table1
    where field in (select id from table2 where talbe1.fieldn = 'string') or field2 = 'string'
  • index_subquery:使用子查询的结果作为索引来访问另一个表。

possible_keys

根据where/group by修饰的字段,可能使用的索引,并不保证实际执行时一定会使用这些索引,可以有多个。

key

表示实际选择的索引。

keylen

索引字段的最大长度,单位字节,值越大越好,主要对于联合索引有参考意义。
注意这里的越大越好,是跟当前字段的情况比较,如int类型占4个字节,显示4或者5(包含null)就很好。如果是varchar(100),则显示400,或403(utf8mb4+null+记录长度的字节 ==> 100 * 4 + 1 + 2,如果字段不为null,则省掉一个字节),比显示260更好。

ref

索引列做等值查询时,与索引列进行等值匹配的对象信息,对性能优化参考意义不大。
例如等值匹配到了,返回const。

rows

预估本次查询要扫描的行数,值越小越好,小了代表范围精准,进而实现快速查找。

filtered

该filtered列指示按表条件过滤的表行的估计百分比。越大越好。最大值为 100,这意味着没有发生行过滤。
从 100 开始递减的值表示过滤量的增加。。例如如果 rows为 1000, filtered为 50.00 (50%),则与下表连接的行数为 1000 × 50% = 500。

Extra

用于备注补充。

  • Using temporary:表示SQL使用union创建的临时表所在行。
  • Using index 表示查询使用了覆盖索引,即只使用了索引而没有访问实际的数据行,这通常发生在查询条件中包含了索引覆盖的所有列。
  • Using where 表示查询使用了 WHERE 子句过滤数据。
  • Using temporary 表示查询需要创建临时表来处理结果集,这可能发生在使用了临时表进行排序操作或者连接操作时。
  • Using filesort 表示查询需要对结果集进行文件排序操作,这通常发生在无法使用索引完成排序时。
  • Using join buffer 表示查询使用了连接缓冲区来处理连接操作。
  • Impossible WHERE 表示 WHERE 子句的条件总是为 false,因此查询将返回空结果集。
  • Select tables optimized away表示由于某些优化,查询将跳过不必要的表访问。
  • Full table scan 表示查询将对整个表进行全表扫描,没有使用任何索引。
  • Using index condition:表示使用了索引下推。
  • Using index for group-by:表示查询使用了索引进行分组操作。
  • Using index for order by:表示查询使用了索引进行排序操作。
  • Using index for distinct 表示查询使用了索引进行去重操作。
  • Using index for limit:表示查询使用了索引来执行 LIMIT 操作。
  • Using index for merge:表示查询使用了索引合并进行连接操作。
  • Using where with pushed condition:表示查询的 WHERE 条件中的部分条件被推迟执行。
  • Loose index scan: 表示在一些情况下,MySQL 可能对索引的列进行宽松扫描,而不是精确匹配。
  • Range checked for each record: 表示对于每个匹配的记录,都需要进一步检查范围条件。
  • Using index for LIKE: 表示使用索引执行了 LIKE 查询。
  • Distinct: 表示在处理查询数据时会进行去重操作。
  • Order by: 表示查询需要进行排序操作。
  • Table is marked as crashed and should be repaired: 表示表已标记为损坏,需要修复。
  • No tables used: 表示查询使用了某种优化方式,无需访问任何表。
  • Range checked for each record (index map: N): 和 Range checked for each record 类似,但额外说明了哪个表进行了进一步的范围检查。

扩展

explain 支持使用原生SQL进行json格式输出,用法explain format=json sql...。