Mysql高级(四) explain 详解

前言:explain(执行计划),使用explain关键字可以模拟优化器执行sql查询语句,从而知道MySQL是如何处理sql语句。explain主要用于分析查询语句或表结构的性能瓶颈。

一、explain的作用

通过explain+sql语句可以知道如下内容:
a、表的读取顺序。(对应id)
b、数据读取操作的操作类型。(对应select_type)
c、哪些索引可以使用。(对应possible_keys)
d、哪些索引被实际使用。(对应key)
e、表直接的引用。(对应ref)
f、每张表有多少行被优化器查询。(对应rows)

mysql explain.jpg

二、id

select 查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序

explain select * from sql.t_order as a, t_goods as b where a.goodsId = b.id;

explain select a.userId from sql.t_order as a where a.goodsId = ( select id from  sql.t_goods as b);

explain  select * from sql.t_user_address as c where c.userId in ( select a.userId from sql.t_order as a where a.goodsId = ( select id from  sql.t_goods as b))

2.1 id相同

id相同,执行顺序自上而下

图片.png

2.2 id不同

id不同,如果是自查询,id大的优先执行

2.3 id相同又不同

id相同又不同,id大的优先执行,id相同的顺序执行

三、select_type

-- 01、SIMPLE
explain select * from sql.t_order as a, t_goods as b where a.goodsId = b.id;

-- 02、PRIMARY & SUBQUERY
explain select a.userId from sql.t_order as a where a.goodsId = ( select id from  sql.t_goods as b);

-- 03、DERIVED
explain  select * from  ( select a.userId, b.id from sql.t_order as a  left join  sql.t_goods as b on a.goodsID = b.id ) as e;

-- 04、UNION & UNION RESULT
explain select a.userId from   sql.t_order as a  where a.id = 1 union select a.userId from   sql.t_order as a  where a.id = 2

四 、table

显示这一行的数据来自于哪张表

五、type

访问类型, 显示查询使用了何种类型,从最差到最好依次是:
ALL < index < range < ref < eq_ref < const 一般要保证达到 range和ref级别,建议达到ref级别

5.1 system

表中含有单行记录

图片.png

5.2 const

表示通过索引一次就找到了

图片.png

5.3 eq_ref

唯一性索引扫描,对于每个索引键,表中都只有一条记录与之匹配。常见于主键或唯一索引扫描。

图片.png

5.4 ref

非唯一性索引扫描,可能返回多行

5.5 range

只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引,一般就是在你的where语句中出现了between、<、>、in等的查询,这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不会扫描全部索引。

图片.png

5.6 index

Full Index Scan,index与ALL区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据文件小。(也就是说虽然all和index都是读全表,但index是从索引中读取的,而all是从磁盘中读取的)。

图片.png

5.7 ALL

Full Table Scan,全表扫描。

图片.png
-- 01 system
explain select id from (select * from sql.t_goods where id = 1) as a ;

-- 02 const
explain select * from sql.t_user_base where id = 1 ;

-- 03 eq_ref
explain select * from sql.t_user_base as a, sql.t_order as b where a.id = b.userId;

-- 04 ref
explain select * from sql.t_user_base as a, sql.t_order as b where a.phoneNum  = b.phoneNum;

-- 05 range
explain select * from sql.t_order as a  where a.phoneNum  >     "13466668886" and  a.phoneNum  <    "13466668888";

-- 06 index 
explain select id from sql.t_order;

-- 07 all 
explain select *  from sql.t_order;

六、possible_keys

指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用(该查询可以利用的索引,如果没有任何索引显示 null)

七、key

实际使用到的索引,如果为NULL,则没有使用索引, 查询中若出现了覆盖索引(查询到列表刚好是索引),则该索引仅出现在key列表。

  • 覆盖索引
    如果一个索引包含(或覆盖)所有需要查询的字段的值,称为‘覆盖索引’。即只需扫描索引而无须回表。

只扫描索引而无需回表的优点:
1. 索引条目通常远小于数据行大小,只需要读取索引,则mysql会极大地减少数据访问量。
2. 因为索引是按照列值顺序存储的,所以对于IO密集的范围查找会比随机从磁盘读取每一行数据的IO少很多。
3. 一些存储引擎如myisam在内存中只缓存索引,数据则依赖于操作系统来缓存,因此要访问数据需要一次系统调用
4. innodb的聚簇索引,覆盖索引对innodb表特别有用。(innodb的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询)

八、key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)不损失精确性的情况下,长度越短越好。

九、ref

显示索引的哪一列被使用了,可以是一个常数,哪些列或常量被用于查找索引列上的值。

十、rows

估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数

十一、Extra

该列包含MySQL解决查询的详细信息,有以下几种情况:

11. 1 Using temporary

表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询,常见 group by ; order by。

图片.png

11.2 Using filesort

当Query中包含 order by 或group by 操作,而且无法利用索引完成的排序操作称为“文件排序”。

  • 非索引排序


    图片.png
  • 索引排序


    图片.png

11.3 Using index

select 中使用了覆盖索引,效率不错。如果同时出现Using where , 表示索引被用来索引键值的查找。

  • using index


    图片.png
  • using index & using where


    图片.png

11.4 Using where

表示使用了where 进行过滤。

图片.png

11.5 Using join buffer

使用了链接缓存。

图片.png

11.6 Impossible where

where 中的值总是false, 不能用来获取任何元组。

图片.png

11.7 Select tables optimized away

这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行

11.8 No tables used

Query语句中使用from dual 或不含任何from子句
-- explain select now() from dual;

11.9 distinct

优化distinct 操作, 在找到第一匹配元组后,停止查找同样值的操作

-- 01 using temporayry
explain  select * from (select a.phoneNum, b.subAmount from sql.t_user_base as a, sql.t_order as b where a.phoneNum = b.phoneNum order by b.subAmount) as e;

-- 02 using filesort
explain select userId  from sql.t_order order by subAmount;

-- 通过索引排序
explain select phoneNum  from sql.t_order order by phoneNum;

-- 03 using index
explain select phoneNum  from sql.t_order   ;

-- using index and using where
explain select phoneNum  from sql.t_order where phoneNum = "13466668888"  ;

-- 04 using where
explain select id, phoneNum,subAmount   from sql.t_order where  subAmount > 1;

-- 05 Using join buffer

explain select phoneNum  from sql.t_order where phoneNum = "13466668888"  union select phoneNum  from sql.t_order where phoneNum = "13466668889"  ;

-- 06 Using Impossible where
explain select id, phoneNum,subAmount   from sql.t_order where  0 > 1;

你可能感兴趣的:(Mysql高级(四) explain 详解)