id
id字段表示查询中每个操作的唯一标识符,其值为整数。这个字段主要有以下几个作用:
区分不同的查询:在复合查询(如子查询或联合查询)中,id字段用于区分不同的子查询或查询块。每个子查询或查询块都会有一个唯一的id。
执行顺序:在执行计划中,id值较大的查询步骤先执行。通常,子查询的id值会比父查询的id值大。
层次结构:在一些复杂的查询中,id字段可以帮助理解查询的执行顺序和嵌套关系。
id相同根据select_type决定执行优先级
select_type
- SIMPLE:简单的SELECT查询,不包含子查询或UNION。
- PRIMARY:最外层的查询,即主查询。
- UNION:UNION操作的第二个或后续查询部分。
- DEPENDENT UNION:与UNION相似,但依赖于外层查询。
- UNION RESULT:UNION操作的结果集。
- SUBQUERY:子查询。
- DEPENDENT SUBQUERY:依赖于外层查询的子查询。
- DERIVED:派生表(子查询中的临时表)。
- MATERIALIZED:物化子查询。
type
作为执行计划中参考价值最高的字段,性能由高到低
system: 表只有一行数据(等同于系统表),这是最快的访问类型。
const: 当查询的结果能够用一个常数值满足,且最多返回一行数据。例如通过主键或唯一索引查询单行数据。
eq_ref: 用于联接操作,当只有一个结果行符合从前表的联接条件。这通常发生在使用主键或唯一索引的联接操作中。
ref: 用于使用非唯一索引,或唯一索引的非唯一查询。这意味着多个行可以匹配查询条件。
fulltext: 用于全文索引的搜索。
ref_or_null: 类似ref,但MySQL还会查找具有NULL值的行。
index_merge: 表示查询使用了两个以上的索引进行合并查找。
unique_subquery: 用于IN查询中的优化,替代了一些correlated子查询。
index_subquery: 类似unique_subquery,用于IN子查询,可以返回多个结果行。
range: 使用索引范围扫描来检索行,常见于使用了比较运算符如>, <, IN, 等。
index: 表示全表扫描但只扫描索引,不读取实际的表数据。
ALL: 全表扫描,没有使用索引,这是最慢的类型。
key_len
-
只计算用到的字段:命中索引中使用到的字段长度(需换算成字节),对于复合索引,只会计算使用到的索引字段长度,没有用到的字段是不会计算的
-
长度计算:username,字符数是50,使用的是utf8mb4(一个字符四个字节),所以字节数是50*4=200,存储200的长度需要2个字节,同理email字段需要402,所以是604
ref
显示了用于查找索引记录的值来源:
-
NULL:如果
ref字段显示的是NULL,表示MySQL不需要额外的列或常量来查找,因为整个索引都被扫描。 -
常量:如果
ref字段显示的是const,表示MySQL在查找索引时使用了一个常量值。 -
列名:如果
ref字段显示的是一个列名,表示MySQL在查找索引时使用了这个列的值。发生在连表查询,这里是join,谁为主表是由执行引擎优化策略决定的,一般小的作为主表去连接另一张表,这里对于表o,取出索引字段值,其值作为c表的索引字段值
req_ref是作为里表的存在
rows
需要扫描的行数,一定要注意,并非是满足条件的函数,而是需要扫描的行数,比如下面,满足条件的只有5行,但扫描了10行去找到这5行数据,用到索引的场景,一般是指回表的次数,这是一个预估值而非实际值

extra
-
use where,使用where条件
-
use index,使用索引
-
Using fileSort
文件排序,发生在order by的使用上,如果排序字段不是索引那就会单独进行排序,这个排序就叫做fileSort,查询级别是ALL,这种是绝对要避免的,如果排序字段是索引那就根本用不着排序了,因为索引是已经排好序的,很明显这个时候的查询级别是index了
-
using temporary使用临时表,常见于order by和group by
这是因为数据量比较大的情况,无法一次性读到内存中进行排序,只能一部分一部分地排序,所以需要将已排好序的数据存储起来,与后面的排列好的数据进行有序的合并,需要避免这种情况,性能会很差
possible keys
根据where条件预测的可能命中的索引
key
实际命中的索引,如果possible keys不为空,而key为空就表示索引失效



