explain命令用来查看一个SQL语句的执行计划,了解我们所写的sql有没有执行索引,是不是进行了全表扫描。
一.explain使用方式
在sql语句前加上explain,explain只能解释select操作,其他操作要重写为select后查看执行计划。
eg:
表:
索引:
执行计划
explain select * from user_info where name = '测试';
执行结果:
二.各项结果介绍:
1.id:sql片段执行的顺序
-
id相同 :执行顺序由上到下
-
id不相同 :如果是子查询,id的序号会递增。id值越大,优先级越高,越先被执行。
- 在所有组中,id值越大,优先级越高,越先执行
2.select_type:查询类型
-
SIMPLE
:简单SELECT(不使用UNION或子查询等)。 -
PRIMARY
:查询中若包含任何复杂的子部分,最外层查询则被标记为primary 。 -
UNION
:union语句中的第二个或后面的SELECT语句;若 union 包含在from子句的子查询中,外层 select 将被标记为 derived。例:
-
UNION RESULT
: UNION的结果,union语句中第二个select开始后面所有select。 -
DEPENDENT UNION
:union中的第二个或后面的SELECT语句,取决于外面的查询 -
SUBQUERY
:子查询中的第一个SELECT,结果不依赖于外部查询。 -
DEPENDENT SUBQUERY
:子查询中的第一个SELECT,依赖于外部查询。 -
DERIVED
:派生表的SELECT, FROM子句的子查询。在 from 列表 中包含的子查询被标记为 derived(衍生),MySQL会递归执行这些子查询,把结果放在临时表中。 -
UNCACHEABLE SUBQUERY
:一个子查询的结果不能被缓存,必须重新评估外链接的第一行
3.table:sql片段所对应的表
4.type:索引类型
常用的类型有: all、index、range、 ref、eq_ref、const、system、null(从左到右,性能从差到好)
-
all
:最坏的情况, 从头到尾全表扫描 -
index
:全索引扫描,index与all区别为index类型只遍历索引树(index 是从索引中读取的,而 all 是从硬盘)。扫描表的时候按照索引次序进行而不是行,主要优点就是避免了排序, 但是开销仍然非常大。 -
range
:使用索引范围查询。这个类型通常出现在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中。它开始于索引的某一点,而结束于索引的另一点,不用扫描全部索引,所以优于index
。 -
ref
:除唯一或非主键索引外,使用普通索引,返回符合条件的所有行。 叫做ref是因为索引要跟某个参考值相比较. 这个参考值或者是一个数, 或者是来自一个表里的多表查询的结果值。 例:'SELECT * FROM tbl WHERE idx_col=expr;'
-
eq_ref
:跟ref
类似,区别是eq_ref
常用于主键或唯一索引扫描,每个索引键值,表中只有一条记录匹配。读取本表中和关联表表中的每行组合成的一行。除 了 system 和 const 类型之外, 这是最好的连接类型。例:'SELECT * FROM reftable,tbl WHERE reftable.key_column=tbl.column;'
-
const
:用于针对主键或唯一索引的等值查询扫描,最多只返回一行数据,所以很快。const
与eq_ref
的区别:const是直接按主键或唯一键读取,eq_ref用于联表查询的情况,按联表的主键或唯一键联合查询。 -
system
:system是const类型的特例,当表中只有一行的情况下,使用system
。 -
null
:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。
5.possible_keys:可能使用的索引。
显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
6.key:表示实际使用的索引。
若为null,则表示没有使用到索引。原因:a.字段没建对应的索引;b.索引已建,但是查询条件导致索引失效(如or
、like
、!=
、<
)。
7.key_len:索引字段的可能最大长度
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)。
不损失精确性的情况下,长度越短越好 。
key_len 的计算规则:
-
字符串
char(n):n 字节长度
varchar(n):如果是 utf8 编码, 则是( 3 n + 2)个字节;如果是 utf8mb4 编码, 则是 (4 n + 2)个字节。 -
数值类型
tinyint:1字节
smallint: 2字节
mediumint: 3字节
int:4字节
bigint: 8字节 -
时间类型
date:3字节
timestamp: 4字节
datetime: 8字节 - 字段属性: null 属性 占用1个字节。如果一个字段是 not null 的, 则没有此属性。
8.ref:使用索引的列名
显示了在 key
列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),func,N
9.rows:扫描出的行数(估算的行数)
估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数
10.Extra:额外信息
执行情况的描述和说明。
- Using index:只需通过索引就可以从表中获取列的信息,无需额外去读取真实的行数据。如果查询使用的列值仅仅是一个简单索引的部分值,则会使用这种策略来优化查询。
- Using index condition:在mysql 5.6版本后加入的新特性(Index Condition Pushdown)。Using index condition 会先条件过滤索引,过滤完索引后找到所有符合索引条件的数据行,随后用 WHERE 子句中的其他条件去过滤这些数据行
- Using where:不用读取表中所有信息,仅通过索引就可以获取所需数据,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤。
- Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询,常见 group by ; order by
- Using filesort:当Query中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序”
- Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。
- Impossible where:这个值强调了where语句会导致没有符合条件的行(通过收集统计信息不可能存在结果)。
- Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行
- No tables used:Query语句中使用from dual 或不含任何from子句