引言
日常工作中,使用MySQL
的机会还是蛮多的,主要考虑Schema与数据类型优化、如何创建索引、根据业务场景的查询优化。这些想必大家都在高性能MySQL
这本书中看过,可能也比作者理解的深,本文旨在对EXPLAIN
语句使用、分析进行整理。
EXPLAIN
语句是什么?
官网对于EXPLAIN
的作用定义如下:
The EXPLAIN statement provides information about how MySQL executes statements. EXPLAIN works with SELECT, DELETE, INSERT, REPLACE, and UPDATE statements.
简单来讲,EXPLAIN
语句告诉我们MySQL如何执行SQL语句,而我们通过这些信息,可以达到优化SQL语句执行效率的目的。
接下来,就要对EXPLAIN
返回的格式进行了解了,具体如下:
字段名 | 字段描述 |
---|---|
id | 查询语句内SELECT的序列号 |
select_type | SELECT类型 |
table | 访问的表名 |
partitions | 命中分区 |
type | 数据访问类型,下文详细介绍 |
possible_keys | 有关索引,实际情况可能不可用 |
key | MySQL查询优化器实际使用的索引 |
key_len | 索引存储长度 |
ref | 实际使用的索引中,用于比较的常量或列 |
rows | 查询需要读取的行数,innodb引擎是一个衡量效率的指标,有时可能不准确 |
Extra | 查询执行的附加信息,下文详细介绍 |
在分析SQL语句执行时,主要用到的列,分别为
type
、Extra
,下文的测试用例均为官网提供的sakila
数据库,附上下载链接。本文使用MySQL 8.0.12、Navicat 12.1
type列主要出现值(性能从好到差)
- system:表只有一行,const类型的特殊情况。
- const:查询结果最多有一行,多为主键、唯一索引与常量比较的情况。
explain select * from actor where actor_id = 1
- eq_ref:一种特殊的索引查找,MySQL知道最多只返回一条符合条件的记录,使用主键、NOT NULL的唯一索引会看到(用navicat发现结果也是ref)。
explain select * from actor, film_actor where actor.actor_id = film_actor.actor_id and actor.actor_id = 1
- ref:一种索引查找,返回所有匹配某个单个值的行,然而,可能会找到多个符合条件的行,当使用非唯一性索引或者唯一性索引的非唯一性前缀时发生。
explain select * from film where title= 'ACE GOLDFINGER'
- range:范围扫描就是一个有限制的索引扫描, 不用遍历所有索引,例如索引在
BETWEEN
、>
、>
范围内的。
explain select * from film where film_id BETWEEN 1 AND 100
- index:全表扫描,只是MySQL扫描表时按索引次序而不是行。
Extra列中看到“Using index”,说明是覆盖索引,只需要读取索引列,不需要读取行数据。
使用索引次序全表读取。
explain select actor.actor_id from film_actor, actor where film_actor.actor_id = actor.actor_id
- ALL:全表扫描,读取行数据,找到需要的行。
explain select * from film_actor, actor where film_actor.actor_id = actor.actor_id
Extra列主要出现的值
- Using index:使用覆盖索引,避免回表查询行数据。
- Using where:存储引擎检索行后再进行过滤。
- Using temporary:对查询结果排序时会使用一个临时表,尽量避免使用临时表。
- Using filesort:对结果使用一个外部索引排序,而不是按索引次序从表里读取行,需要进行优化。
总结
由于查询优化器的存在,实际运行查询语句会和想的不一致,因此在进行查询语句优化时,最好运行下EXPLAIN
语句,看看是不是和自己想的一致。