SQL优化绕不开的字段explain,本篇文章研究一下explain时,一些常用字段基本含义,MySQL版本 5.7。

EXPLAIN    SELECT diversion_code code,COUNT(*) c FROM
        (SELECT user_id,MIN(create_time) create_time ,diversion_code FROM ct_diversion_user
        GROUP BY user_id)r GROUP BY diversion_code

Explain字段的使用_主键

当我们使用一个稍复杂sql时,会出现如图所示基本条件列,那这些列代表什么?列里面的参数又有什么含义?

Explain中的列

id列

id列的值代表着sql语句执行的顺序,值越大,越优先执行

id列值都相等时,执行顺序为从上而下

select_type列

  • simple:简单查询,只有自己一张表进行操作,不会关联其他表;
EXPLAIN SELECT *FROM ct_product WHERE id =32 ;

Explain字段的使用_查询语句_02

  • primary:复杂查询中最外层的 select,语句中最后的查询层;
  • subquery:在select(...)from之中的查询语句;
  • derived:在select * from 之后的的查询语句;
  • union:在union中后的select查询语句,但是在from后的查询语句中有union则为derived;
EXPLAIN
SELECT shop_id FROM ct_product UNION SELECT shop_id FROM ct_shop;

Explain字段的使用_二级索引_03

EXPLAIN
SELECT * FROM (SELECT shop_id FROM ct_product UNION all select 1) a

table列

EXPLAIN
SELECT * FROM (SELECT shop_id FROM ct_product UNION SELECT shop_id FROM ct_shop) a

Explain字段的使用_查询语句_04

  • table列表式执行的哪一个表,当是<derivedN>时,id=N;
  • table列的值为<union2,3>时,2、3为id列值,表式参与了union的有id=2行和id=3行;

type列

表示关联类型或访问类型。

type列常见值有system > const > eq_ref > ref > range > index > ALL  SQL优化时,应将级别保证range以内,若能达到ref最好

当值为null时,意味着执行时不用再访问表或索引,结果直接得到,很少出现。

EXPLAIN SELECT min(id) FROM ct_product;

Explain字段的使用_二级索引_05

  • system、const:意味着MySQL可以将SQL优化为常量查询,大多用于搜索条件是主键索引和唯一索引,索引查询出的结果只有一行结果,system是const的特例,当要查询的表里有且仅有一条数据时,当为system;
  • eq_ref:两张表连接时,连接部分的主键索引和唯一索引的所有部分都被连接使用(一般不会出现);
  • ref:使用普通索引或者唯一索引的部分前缀,可能出现多个值;
  • range:范围扫描,多出现在in(),between,>,<等操作中;
  • index:扫描全索引,一般扫描二级索引,然后得到主键索引,回表得到数据。这个级别比ALL好一点点,但不多
  • all:全表扫描,没有索引,或索引没有用。

possible_keys列

显示可能会走的索引,为null时,则认为没有要走的索引,或者是走的索引对查询帮助不大从而走了全表扫描。

key列

显示走的哪一个索引。

key_len列

显示索引里使用的字节数,可以通过计算得到索引中具体使用了哪些索引。

key_len计算规则如下:

字符串,char(n)和varchar(n),5.0.3以后版本中,n均代表字符数,而不是字节数,如果是utf-8,一个数字或字母占1个字节,一个汉字占3个字节

char(n):如果存汉字长度就是 3n 字节

varchar(n):如果存汉字则长度是 3n + 2 字节,加的2字节用来存储字符串长度,因为varchar是变长字符串

数值类型

tinyint:1字节

smallint:2字节

int:4字节

bigint:8字节  

时间类型 

date:3字节

timestamp:4字节

datetime:8字节

如果字段允许为 NULL,需要1字节记录是否为 NULL。

filtered列

该列是一个百分比的值,rows * filtered/100 可以估算出将要和 explain 中前一个表进行连接的行数(前一个表指 explain 中的id值比当前表id值小的表)。

Extra列

展示的是额外信息,仅供参考,不可作为依据。

  • Using index:覆盖索引,一般用于二级索引,在二级索引中可直接得到想要得到的结果,不需要再回表查询原表。
#shop_id 为普通索引
select shop_id from ct_shop where shop_id='465546545646';
  • Using where:使用 where 语句来处理结果,并且查询的列被全表扫描;
  • Using index condition:查询的列不完全被索引覆盖,where条件中是一个前导列的范围;
  • Using temporary:mysql:需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先是想到用索引来优化;
  • Using filesort:将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。