这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
MySQL中提供explain关键字可以模拟优化器执行SQL语句,从而知道MySQL是如何执行SQL语句的,进而可以分析SQL语句的性能瓶颈,为优化我们的SQL语句提供帮助.MySQL5.6之前,只支持select,MySQL5.6之后,explain支持对select、update、delete语句进行分析。
各字段的含义
id
SQL查询的序列号,可以分析出SQL语句中操作表的顺序
- 如果id相同,则执行顺序为从上到下
如以上执行结果:SQL语句操作表的顺序为:先操作表e,再操作ps、j、d、 n表
- 如果是子查询,id序号会递增,则id越大,其越先被执行
如以上执行结果(SUBQUERY表示子查询):SQL语句操作表的顺序为:先操作表t3,再操作t2,,最后操作表t1(id越大,优先级越高,越先被执行)
- id不同,且存在重复的id,则id越大的越先被执行,相同id序号的则执行顺序为从上到下。
select_type
表示SQL的查询类型
- SIMPLE:简单的select查询,不包含子查询或者UNION
- PRIMARY:查询中若包含任何复杂的子部分,则最外层查询被标记为PARIMARY类型
- SUBQUERY:在select或where中包含子查询
- DERIVED:在from列表中包含的子查询会被标记为DERIVED(衍生的)MySQL会递归执行这些子查询,把结果放在临时表中。
- UNION:若第二个select出现在union之后,则被标记为UNION;若union包含在from子句的子查询中,则外层select会被标记为DERIVED
- UNION RESULT:从union表获取结果的select(即union合并两个表后的结果)会被标记为UNION RESULT
如
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2
的执行结果如下:
table
查询的表名,不一定是实际存在的表名。
-
<unionM,N>: 引用id为M和N UNION后的结果。
-
< derivedN>: 引用id为N的结果派生出的表。派生表可以是一个结果集,例如派生自FROM中子查询的结果。
-
< subqueryN>: 引用id为N的子查询结果物化得到的表。即生成一个临时表保存子查询的结果。
type
表示查询使用的类型(12种) 其查询效率从左到下=右递减
- system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > range > index > ALL
以下列举几个常见的:
-
system:表中只有一行数据或者是空表,如果是Innodb引擎表,type列在这个情况通常都是all或者index。
-
const:表示通过索引一次就查找到,因为只匹配一行,所以能够很快就查询出来,如将
主键=某个值
放在where的后面,MySQL就会将该查询转换为一个常量。 如:EXPLAIN SELECT * FROM t1 WHERE t1.id=1
- eq_ref:唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配,如主键索引或唯一索引。
- ref:非唯一索引扫描,返回匹配某个单独值的所有行。
- range:范围扫描,值检索给定范围的记录,使用一个索引来选择符合的记录。如在where语句中使用了between、<、>、in等的查询。 如
EXPLAIN SELECT * FROM t1 WHERE id>2
(id为主键索引,如果不是索引,会造成全表扫描) - index:扫描所有索引,index与ALL的区别为index类型只遍历索引树,虽然说ALL和index都是读全表,但是index是从索引中读的,而ALL是从磁盘中读的,所以index通常比index快。
- ALL:全表扫描已找到匹配的记录。
possible_keys
显示SQL查询可能使用到的索引的名称
key
显示SQL查询真正使用到的索引的名称
key_len
表示SQL查询用到的索引长度(字节数)
- key_len表示的值为索引字段的最大可能长度,并非实际使用长度,key_len是通过表字段的定义得到的,而不是通过表内检索出来的。
ref
显示索引的哪一列被使用了
- 如果是使用常数等值查询,则为const,如
EXPLAIN SELECT * FROM t1 WHERE id=2
。也可以是表示哪些列被用来查找在索引列上的值,如EXPLAIN SELECT * FROM USER WHERE uname IN (SELECT uname FROM USER WHERE uid>3 )
,以下执行结果ref字段中的demo.user.uname
就表示uname字段的列被用于查找索引列上的值。
rows
估算的需要扫描的行数
- rows可以根据表的统计信息以及索引选用情况,估算出找到目标记录所需要扫描的的行数。
filtered
查询命中率
- 表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例。
extra
表示在其他列中显示但十分重要的额外信息
- Using filesort:表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果。MySQL中无法利用索引完成的排序操作被称为
文件排序
。如EXPLAIN SELECT * FROM t1 ORDER BY age
(age字段上没有建立索引)
-
Using temporary:使用了临时表保存中间结果,MySQL在对查询结果进行排序时会使用临时表。
-
Using index:覆盖索引扫描(
覆盖索引是指SQL所要查询的字段都包含在当前索引的字段中
),表示查询在索引树中就可查找到所需数据, 不用扫描表数据文件(无需回表,所查询的字段都在当前索引的叶子结点上),效率较高。如select id from t1
(id为主键索引) -
Using join buffer:使用了连接缓存
-
impossible where:where子句的值总是false,不能用来获取任何元组。
-
select tables optimized away:在没有Group by子句的情况下,基于索引优化MIN/MAX操作。如
EXPLAIN SELECT MAX(id) FROM t1
(id为主键索引) -
distinct:优化distinct操作,在找到第一个匹配的记录后就停止查找相等值的动作。
🏁以上就是对explain的详细解释,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞吧😻😍