MySQL执行计划
MySQL提供了一个EXPLAIN命令,它可以对SELECT语句进行分析,并输出SELECT执行的详细信息,以便于开发人员可以针对性的进行优化
一:参数说明:
explain 出来的信息有10列,分别为id、select type、table、type、possible keys、key、key len、ref、rows、extra
一、id:
每个select语句都会自动分配的一个唯一标识符
表示查询中操作表的顺序有三种情况:
1. id 相同:执行顺序由上到下。
2. id不同:如果是子查询,id号会自增,id越大优先级越高。
3. id相同的不同的同时存在
id列为null的就表示这是一个结果集,不需要使用它来进行查询。
二、select_type :
查询类型主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询。
1:simple
表示不需要union操作,或者不包含子查询的简单的select查询。有连接 查询时,外层的查询为simple,且只有一个
2:primary
一个需要union操作或者含有子查询的select,位于最外层的查询的 select_type 即为primary,且只有一个
3:union
union 连接的两个select查询,第一个查询是dervied派生表,除了第一个表外,第二个以后的select_type 都是union
4:dependent union
与union一样,出现在union或union all 语句中,但是这个查询要受到外部查询的影响
5:union result
包含union的结果集,在union和union all语句中,因为它不需要查询,所以id字段为null
6:subquery
除了from字句中的子查询外,其它地方出现的子查询都可能是subquery
7:dependent subquery
与dependent union 类似,表示这个subquery的查询要受到外部表查询的影响
8:derived
from字句中出现的子查询,也叫做派生表,其它数据库中可能叫做内联试图或嵌套select。
三:table
1:显式查询表名,如果查询使用了别名,那么这里显式的是别名。
2:如果不涉及对数据库表的操作,那么这里显式为null。
3:如果显式为尖括号括起来的就表示这个是临时表,后面的N就是执行计划中的id,表示结果来自于这个查询产生。
4:如果尖括号括起来的<union M ,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。
四: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,除此之外,MySQL会额外扫描出包含NULL值的行。这种连接方式通常用于有子查询的情形下。
7:unique_subquery
这种连接方式在某种情况下会代替eq_ref,如value IN (SELECT primary_key FROM single_table WHERE some_expr),这种方式使用索引查询功能代替子查询,以获得更好的执行效率。
8:index_subquery
这种连接方式类似unique_subquery。它会代替IN子查询,但是它适用于非unique索引的子查询,用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重
如value IN (SELECT key_column FROM single_table WHERE some_expr)
9:range
索引范围扫描,常见于使用>,<,is null,between,in,like等运算符的查询中。
10:index_merge
表示查询使用了两个以上的索引,最后取交集或者并集,常见and,or的条件使用了不同的索引。
11:index
索引全表扫描,把索引从头到尾扫一遍,常见于使用索引列,就可以处理不需要读取数据文件的查询,可以使用索引排序或者分组的查询。
12:all
全表扫描数据文件,然后在server层进行过滤,返回符合要求的记录。
五:possible_keys
此次查询中可能选用的索引,一个或多个。
六:key
查询真正使用到的索引,select_type为index_merge时,这里可以出现两个以上的索引,其它的select_type这里只会出现一个
七:key_len
用于处理查询的索引长度,
如果单列索引,那就整个索引长度算进去,
如果多列索引,可能用到所有的列,也可能用到部分的列,所以组合索引的key_len是不一定的,通过观察组合索引的key_len,可以预估使用到了组合索引中的哪一部分。
key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中
八:ref
如果使用的是常数等值查询,这里会显示const
如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段
如果是条件使用了表达式或者函数,或者条件发生了内部隐式转换,这里可能显示为func。
九:rows
这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MYISM是精确的值,主要原因是InnoDB中使用了MVCC并发机制)。
十:extra
这个列包含不适合在其它列中显示但十分重要的额外信息,这个列可以显示的信息非常多,有几十种,常用的有:
1:distinct
在select部分使用了distinc关键字
2:no table used
不带from字句的查询或者from dual哑表查询
3:使用 not in()形式子查询或者 not exists运算符的连接查询,这种叫做反连接
即,一般连接查询是先查询内表,在查询外表,反连接就是先查询外表,在查询 内表。
4:using filesort
排序时无法使用到索引时,就会出现这个,常用于order by和group by 语句
说明MySQL会使用一个外部的索引排序,而不是按照索引排序进行读取
MySQL中无法利用索引完成的排序操作称为“文件排序”
5:using index
查询时不需要回表查询,直接通过索引就可以获取查询的数据。
表示相应的select查询中使用到了覆盖索引(Covering Index),避免访问表的数据行,效率不错
如果同时出现Using where ,说明索引被用来执行查找索引键值
如果没有同时出现Using where,表明索引用来读取数据而非执行查找动作。
6:using where
表示存储引擎返回的记录并不是所有的都满足查询条件,而需要在server层进行过滤,查询条件中分为限制条件和检查条件,5.6之前存储引擎只能根据限制条件扫描数据并返回,然后server层根据检查条件进行过滤在返回真正符合查询的数据。5.6.x之后支持ICP特性,可以把检查条件也下推到存储引擎层,不符合检查条件和限制条件的数据,直接不读取,这样就大大减少了存储引擎扫描的记录数量,extra列显式
7:using temporary
表示使用了临时表存储中间结果
MySQL在对查询结果order by和group by时使用临时表
临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,used_tmp_table,used_tmp_disk_table才能看出来