explain Mysql执行计划各字段意义及关键字执行顺序
id : sql语句中有一个select, 那么就会分配一个id
select_type :
*1.SIMPLE*(简单查询)
*2.PRIMARY*(主查询)(一些由多个select 拼接出来的查询分主次,比如 union,union all ,子查询,一般最左边的是主查询)
*3.UNION*(union 查询)UNION主要是针对union,union all两种查询来说的,如果最左边的是PRIMARY,那么剩下的就是UNION
*4.SUBQUERY*(子查询)
table : sql执行计划的每一步都涉及的表,具体是对哪一张表的操作
partitions : 如果查询是基于分区表的话,会显示查询将访问的分区
type : 表示查询访问方法
依次从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引
1:system:表中只有一行数据或者是空表,且只能用于myisam和memory表。如果是Innodb引擎表,type列在这个情况通常都是all或者index
2:const:使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描
3:eq_ref:出现在要连接过个表的查询计划中,驱动表只返回一行数据,且这行数据是第二个表的主键或者唯一索引,且必须为not null,唯一索引和主键是多列时,只有所有的列都用作比较时才会出现eq_ref
4:ref:不像eq_ref那样要求连接顺序,也没有主键和唯一索引的要求,只要使用相等条件检索时就可能出现,常见与辅助索引的等值查找。或者多列主键、唯一索引中,使用第一个列之外的列作为等值查找也会出现,总之,返回数据不唯一的等值查找就可能出现。
5:fulltext:全文索引检索,要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
6:ref_or_null:与ref方法类似,只是增加了null值的比较。实际用的不多。
7:unique_subquery:用于where中的in形式子查询,子查询返回不重复值唯一值
8:index_subquery:用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。
I:range:索引范围扫描,常见于使用>,<,is null,between ,in ,like等运算符的查询中。
J:index_merge:表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取所个索引,性能可能大部分时间都不如range
K:index:索引全表扫描,把索引从头到尾扫一遍,常见于使用索引列就可以处理不需要读取数据文件的查询、可以使用索引排序或者分组的查询。
L:all:这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
possible_keys : 表示可能用到的索引
key : 最终使用的索引,优化器会挑选成本最低的去执行
key_len : 该索引记录的最大长度的字节数
ref : 如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func
rows : 每一行执行计划的操作的扫描行数,因为走了索引只是过滤了不满足索引字段的记录,and后面可能还有条件过滤,所以需要扫描完后,继续拿满足索引的主键进行回表继续过滤。
filtered : 存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。
extra : extra字段可以更加准确描述你的sql是怎么执行的
1.*No tables used*(说明:查询的时候没有选择表时)
2.*Impossible WHERE*(说明:where 子句条件永远为false)
3.*No matching min/max row*(说明:当我们使用聚合函数Max/Min,但是where子句并没有匹配到任何记录,那么不可能存在Max/Min)
4.*using index*(说明:当我们使用二级索引时,直接使用到覆盖索引不需要回表时)
5.*Using index condition*(说明:对于二级索引回表的情况,能在二级索引过滤掉的都过滤掉,减少回表次数)
6.*Using where*(说明:当where后面条件查询时,但是走不了索引的情况)
7.*Using filesort*(说明:主要是针对排序的,如果查询的记录需要排序,如果没有对应的索引,那么就需要在内存或者磁盘进行排序,这个时候就是Using filesort)
8.*Using temporary*(说明: 当我们用到了临时表(排序,去重,分组)的时候,会触发这个类型的extra)
执行顺序:
1.FROM : 对FROM左边的表和右边的表计算笛卡尔积,产生虚表VT1;
2.ON : 对虚拟表VT1进行ON筛选,只有那些符合条件的行才会被记录在虚拟表VT2中;
3.JOIN :如果是OUT JOIN,那么将保留表中(如左表或者右表)未匹配的行作为外部行添加到虚拟表
4.VT2中,从而产生虚拟表VT3;
5.WHERE :对虚拟表VT3进行WHERE条件过滤,只有符合的记录才会被放入到虚拟表VT4;
6.GROUP BY:根据GROUP BY子句中的列,对虚拟表VT4进行分组操作,产生虚拟表VT5;
7.CUBE|ROLLUP:对虚拟表VT5进行CUBE或者ROLLUP操作,产生虚拟表VT6;
8.HAVING :对虚拟表VT6进行 HAVING 条件过滤,只有符合的记录才会被插入到虚拟表VT7中;
9.SELECT :执行SELECT操作,选择指定的列,插入到虚拟表VT8中;
10.DISTINCT :对虚拟表VT8中的记录进行去重,产生虚拟表VT9;
11.ORDER BY :将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10;
12.LIMIT :取出指定行的记录,产生虚拟表VT11,并将结果返回。