explain
explain 语句执行后返回id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra列。
1、id列
id列的编号是select的序列号,有几个select就有几个id,并且id的顺序是按照select出现顺序增长的,MySQL将select查询分为简单查询(SIMPLE)和复杂查询(PRIMARY)。
复杂查询分为三类:简单子查询、派生表(from语句中的子查询)、union查询。
id列越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行。
2、selecet_type列 select_type表示对应行是简单还是复杂查询,如果是复杂的查询,又是上述三种复杂查询中的那一种。
1、simple:简单查询,查询不包含子查询和union。 2、primary:复杂查询中最外层的select。 3、subquery:包含在select中的子查询(不在from子句中)。 4、derived:包含在from子句中的子查询,MySQL会将结果存放在一个临时表中,也称为派生表。 5、union:在union中的第二个和随后的select。 6、union result:从union临时表检索结果的select。 3、table列 table列表示explain的一行正在访问那个张表。
当from子句中有子查询时,table列是格式,表示当前查询依赖id=N的查询,于是先执行id=N的查询。当有union时,UNION RESULT的table列的值为<union1,2>,1和2表示参与union的select行id。
4、type列 type列表示关联类型或访问类型,即MySQL决定如何查询表中的行,查找数据行记录的大概范围。依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL,一般来说,需要保证查询达到range级别,最好达到ref。
ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
index: Full Index Scan,index与ALL区别为index类型只遍历索引树
range:只检索给定范围的行,使用一个索引来选择行
ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件 const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。
5、possible_keys列 possible_keys列表示显示查询可能使用哪些索引来查找。
explain时可能出现possible_keys列,而key列显示NULL的情况,这种情况是因为表中数据不多,MySQL认为索引对此查询帮助不大,选择全表查询。
如果possible_keys列是NULL,则没有相关的索引。在这种情况下,可以通过检查where子句,是否可以创建一个适当的索引来提高查询效率。
6、key列 key列显示MySQL实际采用哪个索引来优化对该表的查询。
如果没有使用索引,则该列是NULL,如果想要强制使用或忽略possible_keys列中的索引,在查询中使用force index、ignore index。
7、key_len列 key_len列显示MySQL在索引里使用的字节数,通过这个值可以算出具体使用了索引中那些字段。
key_len计算规则如下:
字符串
char(n):n字节长度。 varchar(n):需要占用2字节存储字符串长度,如果字符类型为utf-8,则长度为 3n+2。 数值类型
tinyint:1字节。 smallint:2字节。 int:4字节。 bigint:8字节。 时间类型
date:3字节。 timestamp:4字节。 datetime:8字节。 如果字符允许为NULL,需要1字节记录是否为NULL。
索引最大长度是768字节,当字符串过长时,MySQL会做一个类似左前缀索引的处理,将前半部分的字符提取出来做索引。
8、ref列 ref列显示在key列记录的索引中,表查询值所用到的列或常量,常见的有:const(常量),字段名(例:id)。
9、rows列 rows列是MySQL估计要读取并检测的行数,注意这个不是结果集里的行数。
10、Extra列 Extra列显示额外信息,常见的值有:Using index;Using where;Using where Using index;NULL。
Using index:查询的列被索引覆盖,并且where筛选条件是索引的前导列,是性能高的表现。一般是使用了覆盖索引(索引包含查询的所有字段),对于innodb来说,如果是辅助索引性能会有不少的提升。
Using where:查询的列未被索引覆盖,where筛选条件非索引的前导列。
Using where Using index:查询的列被索引覆盖,并且where筛选条件是索引列之一,但不是索引的前导列,意味着无法直接通过索引查找来查询到符合条件的数据。
NULL:查询的列未被索引覆盖,并且where筛选条件是索引的前导列,意味着用到了索引,但是部分字段未被索引覆盖,必须通过回表来实现,不是纯粹的用到了索引,也不是完全没有用到索引。
Using index condition:与Using where类似,查询的列不完全被索引覆盖,where条件中是一个前导列的查询的范围。
Using temporary:MySQL需要创建一张临时表来处理查询,出现这种情况一般是要进行优化的。
Using filesort:MySQL会对结果使用一个外部索引排序,而不是按索引次序从表里读取行,此时MySQL会根据连接类型浏览符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息,这种情况下一般也是要考虑使用索引来优化查询。
合理使用索引
1.不在索引列上使用函数计算、表达式计算
2.尽量全值匹配,不要模糊匹配,模糊匹配满足最佳左前缀原则
3.范围条件放最后
4.组合索引要使用到第一个字段
5.避免隐式转换