Explain详解与索引优化实践(3)

举例来说,film_actor表的联合索引idx_film_actor_id由film_id和actor_id两个int列组成,并且每个int是4字节。通过下面结果中的key_len=4可推断出只使用了第一个列flim_id来执行索引查找。

执行SQL语句:EXPLAIN SELECT * FROM film_actor WHERE film_id=2

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

(8)ref列

这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量)、字段名(例:film.id)。

(9)rows列

这一列是MySQL估计要读取并检测的行数,注意这个不是结果集里的行数。

(10)Extra列 

这一列展示的是额外信息。常见的重要值如下:

Using index: 查询的列被索引覆盖,并且where筛选条件是索引的前导列(类似联合索引的最左前缀原则),是性能高的表现。一般是使用了覆盖索引(即索引包含了所有查询的字段)。对于InnoDB来说,如果是普通索引性能会有不少提高。

执行SQL语句:EXPLAIN SELECT film_id FROM film_actor WHERE film_id=1

Using where:查询的列不完全被索引覆盖,where筛选条件非索引的前导列。(不走索引,性能较低)

执行SQL语句:EXPLAIN SELECT * FROM actor WHERE

Using where; Using index:查询的列被索引覆盖,并且where筛选条件是索引列之一但不是索引的前导列,意味着无法直接通过索引来查找符合条件的数据。

执行SQL语句:EXPLAIN SELECT film_id FROM film_actor WHERE actor_id=1

NULL:查询的列未被索引覆盖,并且where筛选条件是索引的前导列,意味着用到了索引,但是部分字段未被索引覆盖,必须通过“回表”来实现,不是纯粹地用到了索引,也不是完全没用到索引。

执行SQL语句:EXPLAIN SELECT * FROM film_actor WHERE film_id=1

Using index condition:MySQL 5.6版本开始加入的新特性,与Using where类似,查询的列不完全被索引覆盖,where条件中是一个前导列的范围。

执行SQL语句:EXPLAIN SELECT * FROM film_actor WHERE film_id>1

Using temporary:MySQL需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先要想到用索引来优化。

① actor.name没有索引,此时创建了一张临时表来distinct。(distinct:去除查询结果中的重复记录)

执行SQL语句:EXPLAIN SELECT DISTINCT NAME FROM actor

② film.name建立了idx_name索引,此时查询时extra是Using index,没有用临时表。

执行SQL语句:EXPLAIN SELECT DISTINCT NAME FROM film

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e29ab88dd33cafa3b0071b471ee0ab56.html