数据库索引系列三:EXPLAIN使用详解

explain用于查看一条sql语句如何使用索引来查询以及连接表,旨在帮助我们使用好索引和写出高性能的查询sql。
数据库索引系列三:EXPLAIN使用详解_第1张图片

举例:

EXPLAIN SELECT s.uid,s.username,s.name,f.email,f.mobile,f.phone,f.postalcode,f.address 
FROM uchome_space AS s,uchome_spacefield AS f 
WHERE 1 
AND s.groupid=0 
AND s.uid=f.uid;

它的执行结果是:
这里写图片描述
下面我们先分析一下sql解析的结果:
1. id

select识别符。这是select查询序列号,并不是sql语句执行的顺序,执行顺序是由引擎决定的。id为null的就表示这是一个结果集,不需要使用它来查询。看下面这条sql:
EXPLAIN SELECT * FROM (SELECT * FROM uchome_space LIMIT 10) AS s;
它的执行结果是:
这里写图片描述
可以看到这时的id变化了。

2. select_type

select类型,它有以下几种值:
2.1 simple:标识简单的sql,没有union和子查询;
2.2 primary:最外面的select,在有子查询的语句中,最外面的select查询就是primary。
2.3 union:union语句第二个或者说是后面那一个。例如:
select * from uchome_space limit 10 union select * from uchome_space limit 10,10;
执行结果如下:
这里写图片描述
2.4 dependent union:union中的第二个或后面的select语句,但是这个查询要依赖于外面的查询;
2.5 union result:union查询的结果;
2.6 derived:from字句中出现的子查询,也叫派生表。
2.7 subquery:除了from字句中包含的子查询外,其他地方出现的子查询都可能是subquery;
2.8 dependent subquery:与dependent union类似,表示这个subquery的查询要收到外部表查询的影响。
EXPLAIN SELECT *,(SELECT a.name FROM user u WHERE u.id=i.userId) as userName FROM info i LIMIT 1;
这里写图片描述
2.9 materialized:物化子查询,不太清楚,a这个值查询出来是null
数据库索引系列三:EXPLAIN使用详解_第2张图片
3. table
输出的行所用的表。
3.1 如果查询使用了别名,那么这里显示的是别名;
3.2 如果不涉及对数据表的操作,那么这里显示为null;
3.3 如果显示为< derived N>就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生;
3.4 如果是< union M,N>,也是临时表,表示这个结果来自于union查询的id为M和N的结果集。
4. type
依次从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL。除了ALL以外,其他的type都用到了索引,除了index_merge之外,其他的type只可以用到一个索引。
4.1 system:表中只有一行数据或者是空表,且只能用于myisam和memory表。如果是innodb引擎,type通常是ALL或index;
如:数据库索引系列三:EXPLAIN使用详解_第3张图片
4.2 const:使用唯一索引或者主键,返回记录一定是一行记录的等值where条件时,通常type是const。其他数据库也叫唯一索引扫描;
数据库索引系列三:EXPLAIN使用详解_第4张图片
4.3 eq_ref:出现在要连接多个表的查询计划中,驱动表只返回一行数据,且这行数据是第二个表的主键或唯一索引,且必须为not null。唯一索引和主键是多列时,只有所有的列都用作比较时才会出现eq_ref;如2.8图。
4.4 ref:不像eq_ref那样要求连接顺序,也没有主键和唯一索引的要求,只要使用相等(即“=”符号)条件检索时就可能出现,常见于辅助索引的等值查找。或者多列主键、唯一索引的联合索引中,使用第一个列之外的列作为等值查找也会出现,总之,返回数据不唯一的索引等值查找就有可能出现。
explain select * from uchome_space where uchome_space.friendnum = 0;
这里写图片描述
4.5 fulltext:全文索引检索,要注意,全文索引的优先级很高,若全文索引与普通索引同事存在,MySQL不管代价,优先使用全文索引,全文索引只存在于myisam引擎数据库中。
4.6 ref_or_null:与ref方法类似,只是增加了null值的比较,实际用的不多。
4.7 unique_subquery:用于where中的in形式子查询,子查询返回不重复值唯一值。
4.8 index_subquery:用于in形式子查询使用到了辅助索引子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可使用索引将子查询去重。
4.9 range:索引范围扫描,常见于使用< , > , is null , between
, in , like等运算符的查询中。
4.10 index_merge:表示查询使用了两个以上的索引,最后取交集或者并集,常见and,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间不如range。
4.11 index:索引全表扫描,把索引从头到尾扫一遍,常见于使用索引列就可以处理不需要读取数据文件的查询、可以使用索引排序或者分组的查询。
4.12 all:全表扫描数据文件,然后再在server层进行过滤后返回符合要求的数据。
5. possible_keys
查询可能使用到的索引都会在这里列出来
6. keys
查询真正使用到的索引。
注:select_type为index_merge时,这里可能出现两个以上的索引,其他的只有一个。
7. key_len
用于处理查询的索引长度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查询不一定都能使用到所有的列,where条件里具体使用到多少个列的索引,这里就会计算进去,没有使用到的列或排序分组使用的索引,这里不会算进去。
8. ref
用来标识那些用来进行索引比较的列或者常量
8.1. 如果是使用的常数等值查询,这里会显示const;
8.2. 如果是子查询,这里显示驱动表关联的列名;
这里写图片描述
8.3. 如果是表连接查询,被驱动表的执行计划这里会显示驱动表的关联字段;
8.4. 如果是条件使用了表达式或者函数,或者条件发生了内部隐式转换,这里可能显示为func;
9. rows
这里是执行计划中估算的扫描行数,不是精确值。
10. extra
这个列可以显示的信息非常多,有几十种,常用的有:
10.1. distinct:在select部分使用了distinct关键字
10.2. no table used:不带from字句的查询或者from dual查询
数据库索引系列三:EXPLAIN使用详解_第5张图片
10.3. Using where:表示存储引擎返回的记录并不是所有的都满足条件,需要在server层进行过滤。查询条件中分为限制条件和检查条件,5.6之前,存储引擎只能根据限制条件扫描数据并返回,然后server层根据检查条件进行过滤再返回真正符合查询的数据。5.6.x之后支持ICP特性,可以把检查条件也下推到存储引擎层,不符合检查条件和限制条件的数据,直接不读取,这样就大大减少了存储引擎扫描的记录数量,extra显示using index condition。
这里写图片描述
10.4. using index:查询时不需要回表查询,直接通过索引就可以获取查询的数据
这里写图片描述
10.5. not in/not exists:使用not in()形式子查询或not exist运算符的连接查询,这种叫作反连接。即,一般连接查询是先查询内表,在查询外表,反连接就是先查外表,再查内表。
10.6. using filesort:排序时无法使用到索引时,就会出现这个。常见于order by或group by语句中。
10.7. using join buffer(block nested loop),using join buffer(batched key accss):5.6.x之后的版本优化关联查询的BNL,BKA特性。主要是减少内表的循环数量以及比较顺序地扫描查询。
10.8. using_union:表示使用or的各个索引的条件时,该信息表示从结果集获取并集
using intersect:表示使用and的各个索引的条件时,该信息表示从结果集获取交集
using sort_union,using sort_intersection:与前面两个类似,只是他们是出现在用and和or查询信息量大时,先查询主键,然后进行排序合并后,才能读取记录并返回。
10.9. using temporary:表示使用了临时表存储中间结果,临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,used_tmp_table,used_temp_disk_table才能看出来。
10.10. firstmatch(tb_name):5.6.x开始引入的优化子查询的新特性之一,常见于where字句含有in()类型的子查询,如果内表数据量比较大,就可能出现这个。
10.11. loosescan(m…n):5.6.x之后引入的优化子查询的新特性之一,在in()类型的子查询中,子查询返回的可能有重复记录时,就可能出现这个。
11. filterred
使用explain extended是会出现这个列,5.7之后的版本默认就有这个列,不需要使用explain extended了。这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例。
这里写图片描述

你可能感兴趣的:(mysql,数据库,索引,高性能)