EXPLAIN 获取执行语句计划
Posted VVL1295
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了EXPLAIN 获取执行语句计划相关的知识,希望对你有一定的参考价值。
可以通过 EXPLAIN 获取执行语句计划,从而优化语句。
会显示如下信息:
其中,id:select 语句的 ID;
select_type:查询的基本类型(例如,简单的查询,union 查询,衍生表查询,即 from 子句里的子查询);
table:输出的记录所在的 table;
partitions:与表的分区有关,暂时不能总结;
type:join type,描述了查询的连接类型(密切影响性能),有很多种类;
possible_keys:在表中可被使用的索引;
key:mysql 选择使用的索引;
key_length:MySQL 选择使用的索引的长度,这允许你决定 MySQL 使用复合索引的哪些部分;
ref:与索引列作比较的列或者常量(例如,常量:where indexColumn = 1;列:where indexColumn = (select max(sth) from table))(版本 5.7.3 前需要使用语句 EXPLAIN EXTENDED 才能显示);
rows:MySQL 认为必须检查的数据行数;
filtered:MySQL 估计的查询出来的记录数占全部记录数的百分数(版本 5.7.3 前需要使用语句 EXPLAIN EXTENDED 才能显示);
extra:MySQL 处理语句的额外的信息;
详细解释 type:MySQL 如何进行连表查询(JOIN);
值如下,性能由高到低排列:
system:表只有一行数据,const 的一种特殊情况;
const:表最多只有一行匹配的记录,因为表只有一行匹配的记录;且记录里面的值会被看作常量;const 表的速度非常快,因为只会被被读一次;
当使用全主键(例如,有复合主键 PK(p1, p2),要 p1,p2两个都被用上)或全索引与常量进行比较时,const 就会被使用;在下面的语句中,table1 被用作 const 表;
SELECT * FROM tbl_name WHERE primary_key=1; SELECT * FROM tbl_name WHERE primary_key_part1=1 AND primary_key_part2=2;
eq_ref:查询语句读取两个表的数据,当前 table 只有一行会被读取(为了与另一个表的数据一同被查出),不同于以上两个,这是有可能的最后的 join type(不太理解,可能是因为这是最好的且很需要注意的 join type),当整个索引被用上且索引是一个主键或者是 UNIQUE NOT NULL 索引,MySQL 就会选用这种 join type;
当然,也可以在满足上面条件的基础上,把索引列放在 = 条件上,比较的值既可以是常量也可以是另一个表的列(即两个表的列用“=”进行比较);
以下的查询语句会用上 eq_ref,正如上面提到的一样(其实与 const 不同的地方就是 SQL 会查两个表的记录,const 只查一个表的记录):
SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
ref:全部匹配索引值的记录都被读出(为了与另一个表的数据一同被查出),如果语句用了左前缀索引,非主键索引,非 UNIQUE 索引(就是不是只有一行记录会被匹配的情况都会可能使用 ref join type),如果索引只是匹配了一些记录,那这就是一个好的 join type;
可以使用 =,< 和 > 运算符,下面的语句用了 ref join type:
SELECT * FROM ref_table WHERE key_column=expr; SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
fulltext:使用了 FULLTEXT 索引的(全文索引,用于优化对于文本的索引,LIKE sth \'%xxx%\' 这样的性能很低,无法使用索引,而使用 FULLTEXT 索引和 match(field) against (‘text’) 语法能提高文本搜索的速度,但不会对 LIKE sth \'%xxx%\' 有优化);
ref of null:用于查询某些值为 null 的记录;多数用于子查询,以下的例子用到了 ref of null;
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
index image:指明索引合并优化被使用,输出内容包含了被用上的索引,而 key_len 包含多个被用上的索引的 最长的部分(复合索引);
index subquery:类似于 unique subquery,代替了 IN 子查询,子查询中 nonunique 索引会用上这个 join type,下面的例子会用上这个 join type:
value IN (SELECT key_column FROM single_table WHERE some_expr)
range:只有在给定范围里的记录会被获取,使用一个索引去查询记录;使用这个 join type 时,ref 的值会是 null;
当一个索引列用在 =
, <>
, >
, >=
, <
, <=
, IS NULL
, <=>
, BETWEEN
, 或者 IN()
操作符的时候,会用上这个 join type,例子如下:
SELECT * FROM tbl_name WHERE key_column = 10; SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20; SELECT * FROM tbl_name WHERE key_column IN (10,20,30); SELECT * FROM tbl_name WHERE key_part1 = 10 AND key_part2 IN (10,20,30);
index:几乎跟 ALL 一样,不过这个 join type 代表着索引树被扫描,全部索引被扫描,出现在两种情况:
1,如果索引是一个覆盖的索引,而且满足所有要获取的数据,然后索引树就会被扫描,Extra 的值就会为 Using index,通常比 ALL 好,因为通常索引的数量会小于表的记录数(即通常不会存在全部记录都与这个索引的值匹配上的情况);
2,当按着索引的顺序查找记录的时候就会进行全表扫描,Extra 的值就不会是 Using index;
当语句只是用一个索引的一部分的时候,MySQL 会使用这种 join type;
All:如果表是 the first table,但是不是 const,那么这个 join type 是不好的,在其他情况下是非常不好的;
可以通过添加允许基于常量字段值或 earlier tables 的字段值的列的获取的 index 来避免全表扫描;
Extra 信息(这里暂时不总结,遇到一个就总结一个):
通常注意关注两种信息:
1,Using filesort:看到这个的时候,查询就需要优化了,MySQL 需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行,可能可以通过优化 ORDER BY 进行优化;
2,Using temporary:表明查询需要优化,表示 MySQL 需要创建一个临时表来存储结果,这通常发生在对不同的列集进行 ORDER BY 上,和 GROUP BY 上,要注意避免产生临时表;
以上是关于EXPLAIN 获取执行语句计划的主要内容,如果未能解决你的问题,请参考以下文章