
在MySQL中,咱们能够经过EXPLAIN命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程当中表如何链接和链接的顺序。微信
下面分别对EXPLAIN命令结果的每一列进行说明:post
select_type:表示SELECT的类型,常见的取值有:性能
类型 | 说明 |
---|---|
SIMPLE | 简单表,不使用表链接或子查询 |
PRIMARY | 主查询,即外层的查询 |
UNION | UNION中的第二个或者后面的查询语句 |
SUBQUERY | 子查询中的第一个 |
table:输出结果集的表(表别名)学习
type:表示MySQL在表中找到所需行的方式,或者叫访问类型。常见访问类型以下,从上到下,性能由差到最好:优化
ALL | 全表扫描 |
---|---|
index | 索引全扫描 |
range | 索引范围扫描 |
ref | 非惟一索引扫描 |
eq_ref | 惟一索引扫描 |
const,system | 单表最多有一个匹配行 |
NULL | 不用扫描表或索引 |
type=ALL,全表扫描,MySQL遍历全表来找到匹配行spa
通常是没有where条件或者where条件没有使用索引的查询语句code
EXPLAIN SELECT * FROM customer WHERE active=0;
server
type=index,索引全扫描,MySQL遍历整个索引来查询匹配行,并不会扫描表blog
通常是查询的字段都有索引的查询语句排序
EXPLAIN SELECT store_id FROM customer;
type=range,索引范围扫描,经常使用于<、<=、>、>=、between等操做
EXPLAIN SELECT * FROM customer WHERE customer_id>=10 AND customer_id<=20;
注意这种状况下比较的字段是须要加索引的,若是没有索引,则MySQL会进行全表扫描,以下面这种状况,create_date字段没有加索引:
EXPLAIN SELECT * FROM customer WHERE create_date>='2006-02-13' ;
type=ref,使用非惟一索引或惟一索引的前缀扫描,返回匹配某个单独值的记录行
store_id
字段存在普通索引(非惟一索引)
EXPLAIN SELECT * FROM customer WHERE store_id=10;
ref类型还常常会出如今join操做中:
customer、payment表关联查询,关联字段customer.customer_id
(主键),payment.customer_id
(非惟一索引)。表关联查询时一定会有一张表进行全表扫描,此表必定是几张表中记录行数最少的表,而后再经过非惟一索引寻找其余关联表中的匹配行,以此达到表关联时扫描行数最少。
由于customer、payment两表中customer表的记录行数最少,因此customer表进行全表扫描,payment表经过非惟一索引寻找匹配行。
EXPLAIN SELECT * FROM customer customer INNER JOIN payment payment ON customer.customer_id = payment.customer_id;
type=eq_ref,相似ref,区别在于使用的索引是惟一索引,对于每一个索引键值,表中只有一条记录匹配
eq_ref通常出如今多表链接时使用primary key或者unique index做为关联条件。
film、film_text表关联查询和上一条所说的基本一致,只不过关联条件由非惟一索引变成了主键。
EXPLAIN SELECT * FROM film film INNER JOIN film_text film_text ON film.film_id = film_text.film_id;
type=const/system,单表中最多有一条匹配行,查询起来很是迅速,因此这个匹配行的其余列的值能够被优化器在当前查询中看成常量来处理
const/system出如今根据主键primary key或者 惟一索引 unique index 进行的查询
根据主键primary key进行的查询:
EXPLAIN SELECT * FROM customer WHERE customer_id =10;
根据惟一索引unique index进行的查询:
EXPLAIN SELECT * FROM customer WHERE email ='MARY.SMITH@sakilacustomer.org';
type=NULL,MySQL不用访问表或者索引,直接就可以获得结果
possible_keys: 表示查询可能使用的索引
key: 实际使用的索引
key_len: 使用索引字段的长度
ref: 使用哪一个列或常数与key一块儿从表中选择行。
rows: 扫描行的数量
filtered: 存储引擎返回的数据在server层过滤后,剩下多少知足查询的记录数量的比例(百分比)
Extra: 执行状况的说明和描述,包含不适合在其余列中显示可是对执行计划很是重要的额外信息
最主要的有一下三种:
Using Index | 表示索引覆盖,不会回表查询 |
---|---|
Using Where | 表示进行了回表查询 |
Using Index Condition | 表示进行了ICP优化 |
Using Flesort | 表示MySQL需额外排序操做, 不能经过索引顺序达到排序效果 |
MySQL5.6引入了Index Condition Pushdown(ICP)的特性,进一步优化了查询。Pushdown表示操做下放,某些状况下的条件过滤操做下放到存储引擎。
EXPLAIN SELECT * FROM rental WHERE rental_date='2005-05-25' AND customer_id>=300 AND customer_id<=400;
在5.6版本以前:
优化器首先使用复合索引idx_rental_date过滤出符合条件rental_date='2005-05-25'
的记录,而后根据复合索引idx_rental_date回表获取记录,最终根据条件customer_id>=300 AND customer_id<=400
过滤出最后的查询结果(在服务层完成)。
在5.6版本以后:
MySQL使用了ICP来进一步优化查询,在检索的时候,把条件customer_id>=300 AND customer_id<=400
也推到存储引擎层完成过滤,这样可以下降没必要要的IO访问。Extra为Using index condition
就表示使用了ICP优化。
《深刻浅出MySQL》