如何获取select语句执行计划?
explain sql;
explain 列有哪些?含义?
Column | 含义 |
---|---|
id | 查询序号 |
select_type | 查询类型 |
table | 表名 |
partitions | 匹配的分区 |
type | join类型 |
prossible_keys | 可能会选择的索引 |
key | 实际选择的索引 |
key_len | 索引的长度 |
ref | 与索引作比较的列 |
rows | 要检索的行数(估算值) |
filtered | 查询条件过滤的行数的百分比 |
Extra | 额外信息 |
一、 id
SQL查询中的序列号。
id列数字越大越先执行,如果说数字一样大,那么就从上往下依次执行。
二、 select_type
查询的类型,可以是下表的任何一种类型:
select_type | 类型说明 |
---|---|
SIMPLE | 简单SELECT(不使用UNION或子查询) |
PRIMARY | 最外层的SELECT |
UNION | UNION中第二个或之后的SELECT语句 |
DEPENDENT UNION | UNION中第二个或之后的SELECT语句取决于外面的查询 |
UNION RESULT | UNION的结果 |
SUBQUERY | 子查询中的第一个SELECT |
DEPENDENT SUBQUERY | 子查询中的第一个SELECT, 取决于外面的查询 |
DERIVED | 衍生表(FROM子句中的子查询) |
MATERIALIZED | 物化子查询 |
UNCACHEABLE SUBQUERY | 结果集无法缓存的子查询,必须重新评估外部查询的每一行 |
UNCACHEABLE UNION | UNION中第二个或之后的SELECT,属于无法缓存的子查询 |
其中,DEPENDENT
意味着使用了关联子查询。
三、 table
查询的表名。不一定是实际存在的表名。
可以为如下的值:
-
<unionM,N>
: 引用id为M和N UNION后的结果。 -
<derivedN>
: 引用id为N的结果派生出的表。派生表可以是一个结果集,例如派生自FROM中子查询的结果。 -
<subqueryN>
: 引用id为N的子查询结果物化得到的表。即生成一个临时表保存子查询的结果。
四、 type
这是最重要的字段之一,显示查询使用了何种类型。从最好到最差的连接类型依次为:
system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL
-
除了
all
之外,其他的type都可以使用到索引;· -
除了
index_merge
之外,其他的type只可以用到一个索引。-
1、system
表中只有一行数据或者是空表,这是const类型的一个特例。且只能用于myisam
和memory
表。
如果是Innodb
引擎表,type列在这个情况通常都是all
或者index
。 -
2、const
最多只有一行记录匹配。
当联合主键或唯一索引的所有字段跟常量值比较时,join类型为const。其他数据库也叫做唯一索引扫描 -
3、eq_ref
多表join时,对于来自前面表的每一行,在当前表中只能找到一行。这可能是除了system和const之外最好的类型。当主键或唯一非NULL索引的所有字段都被用作join联接时会使用此类型。
eq_ref
可用于使用'='操作符作比较的索引列。比较的值可以是常量,也可以是使用在此表之前读取的表的列的表达式。
相对于下面的ref区别就是它使用的唯一索引,即主键或唯一索引,而ref使用的是非唯一索引或者普通索引。
eq_ref
只能找到一行,而ref
能找到多行。 -
4、ref
对于来自前面表的每一行,在此表的索引中可以匹配到多行。若联接只用到索引的最左前缀或索引不是主键或唯一索引时,使用ref类型(也就是说,此联接能够匹配多行记录)。
ref
可用于使用'='或'<=>'操作符作比较的索引列。 -
5、 fulltext
使用全文索引的时候是这个类型。要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引 -
6、ref_or_null
跟ref类型类似,只是增加了null值的比较。实际用的不多。 -
7、index_merge
表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间都不如range -
8、unique_subquery
用于where中的in形式子查询,子查询返回不重复值唯一值,可以完全替换子查询,效率更高。
该类型替换了下面形式的IN子查询的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
-
9、index_subquery
该联接类型类似于unique_subquery。适用于非唯一索引,可以返回重复值。 -
10、range
索引范围查询,常见于使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN()或者like等运算符的查询中。
SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20; SELECT * FROM tbl_name WHERE key_column IN (10,20,30);
- 11、index
索引全表扫描,把索引从头到尾扫一遍。这里包含两种情况:
一种是查询使用了覆盖索引,那么它只需要扫描索引就可以获得数据,这个效率要比全表扫描要快,因为索引通常比数据表小,而且还能避免二次查询。在extra中显示Using index,反之,如果在索引上进行全表扫描,没有Using index的提示。
# 此表见有一个name列索引。 # 因为查询的列name上建有索引,所以如果这样type走的是index mysql> explain select name from testa; +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ | 1 | SIMPLE | testa | index | NULL | idx_name | 33 | NULL | 2 | Using index | +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ 1 row in set # 因为查询的列cusno没有建索引,或者查询的列包含没有索引的列,这样查询就会走ALL扫描,如下: mysql> explain select cusno from testa; +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | testa | ALL | NULL | NULL | NULL | NULL | 2 | NULL | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ 1 row in set # 包含有未见索引的列 mysql> explain select * from testa; +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | testa | ALL | NULL | NULL | NULL | NULL | 2 | NULL | +----+-------------+-------+------+---------------+------+---------+------+------+-------+ 1 row in set
- 12、all
全表扫描,性能最差。
-
五、 possible_keys
查询可能使用到的索引都会在这里列出来。
六、 key
查询MySQL实际使用到的索引(键)。
要想强制MySQL使用或忽视possible_keys
列中的索引,可以使用FORCE INDEX
、USE INDEX
或者 IGNORE INDEX
。
select_type
为index_merge
时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
七、key_len
查询用到的索引长度(字节数)。
key_len
只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。
八、ref
表示上述表的连接匹配条件,即那些列或常量被用于查找索引列上的值。
如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func
九、 rows
rows 也是一个重要的字段。 这是mysql估算的需要扫描的行数(不是精确值)。
这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好.
十、 Extra
该列包含MySQL解决查询的详细信息,有以下几种情况:
-
Using where
:列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示MySQL服务器将在存储引擎检索行后再进行过滤。 -
Using temporary
:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询。 -
Using filesort
:MySQL中无法利用索引完成的排序操作成为“文件排序”。 -
Using join buffer
:该值强调了在获取连接条件是没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进性能。 -
Impossible where
:这个值强调了where语句会导致没有符合条件的行。 -
Select tables optimized away
:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行。
什么是回表?
在普通索引查到主键索引后,再去主键索引定位记录。(等于说非主键索引多走了一个索引树。)
网友评论