Explain关键字 什么是MySQL的执行计划?( 三 )


【key_len列】 
这一列表明了在索引里使用的字节数 , 通过这个值可以大致估算出具体使用了联合索引中的前几个列 。
key_len计算规则这里不再赘述 , 不同的数据类型所占的字节数是不一致的 。
【ref列】 
这一列表明了在key列记录的索引中 , 表查找值所用到的列或常量 , 常见的有:const(常量) , 字段名 , 如user.user_id
【rows列】 
这一列表明优化器大概要读取并检测的行数 。跟实际的数据行数大部分情况是不一致的 。
【Extra列】 
顾名思义 , 这一列表明的是额外信息,这一列的取值对优化SQL非常有参考意义 。常见的重要取值如下:
 
1)using index:所有被查询的字段都是索引列(称为覆盖索引),并且where条件是索引的前导列 , 出现这样的结果 , 是性能高的表现 。
explainselect group_id,group_name from t_group;

Explain关键字 什么是MySQL的执行计划?

文章插图
 
2)using where:被查询的列未被索引覆盖 , where条件也并非索引的前导列 , 表示 MySQL 执行器从存储引擎接收到查询数据,再进行“后过滤”(Post-filter) 。所谓“后过滤” , 就是先读取整行数据 , 再检查此行是否符合 where 句的条件 , 符合就留下 , 不符合便丢弃 。
explain select * from t_user whereuser_name='user1';
Explain关键字 什么是MySQL的执行计划?

文章插图
 
3)using where Using index:被查询的列被索引覆盖 , 并且where条件是索引列之一但是不是索引的前导列 , 也就是没有办法直接通过索引来查询到符合条件的数据
explain select * from t_group where group_name = 'group1';
Explain关键字 什么是MySQL的执行计划?

文章插图
 
4)null:被查询的列没有被索引覆盖 , 但where条件是索引的前导列 , 此时用到了索引 , 但是部分列未被索引覆盖 , 必须通过“回表查询”来实现 , 不是纯粹地用到了索引 , 也不是完全没用到索引
explain select * from t_user where user_id='1';
Explain关键字 什么是MySQL的执行计划?

文章插图
 
5)using index condition:与using where类似 , 查询的列不完全被索引覆盖 , where条件中是一个前导列的范围;这种情况未能通过示例显现 , 可能跟MySQL版本有关系 。
 
6) using temporary:这表明需要通过创建临时表来处理查询 。出现这种情况一般是要进行优化的 , 用索引来优化 。创建临时表的情况:distinct , group by , orderby , 子查询等
 
explain select distinct user_name from t_user;
Explain关键字 什么是MySQL的执行计划?

文章插图
 
explain select distinct group_name fromt_group; --group_name是索引列
Explain关键字 什么是MySQL的执行计划?

文章插图
 
7) usingfilesort:在使用order by的情况下出现 , mysql会对结果使用一个外部索引排序 , 而不是按索引次序从表里读取行 。此时mysql会根据连接类型浏览所有符合条件的记录 , 并保存排序关键字和行指针 , 然后排序关键字并按顺序检索行信息 。这种情况下要考虑使用索引来优化的 。
 
explain select * from t_user orderby user_name;
Explain关键字 什么是MySQL的执行计划?

文章插图
 
explain select * from t_group order bygroup_name; --group_name是索引列
Explain关键字 什么是MySQL的执行计划?

文章插图
 
查询优化建议 
结合前面的描述 , 首先看 type列的结果 , 如果有类型是 all 时 , 表示预计会进行全表扫描(fulltable scan) 。通常全表扫描的代价是比较大的 , 建议创建适当的索引 , 通过索引检索避免全表扫描 。
 
再来看下 Extra 列的结果 , 如果有出现 Using temporary 或者 Using filesort 则要多加关注:
 
Using temporary , 表示需要创建临时表以满足需求 , 通常是因为GROUP BY的列没有索引 , 或者GROUP BY和ORDER BY的列不一样 , 也需要创建临时表 , 建议添加适当的索引 。


推荐阅读