目录
由于EXPLAIN的内容较多,所以这里只会摘录一些重要的地方,详情可以参考原文。
EXPLAIN的结果解释:
Column
JSON Name
Meaning
select_id
The SELECT
identifier
None
The SELECT
type
table_name
The table for the output row
partitions
The matching partitions
access_type
The join type
possible_keys
The possible indexes to choose
key
The index actually chosen
key_length
The length of the chosen key
ref
The columns compared to the index
rows
Estimate of rows to be examined
filtered
Percentage of rows filtered by table condition
None
Additional information
摘一些重要的列:
table
即表名,但是也有可能是下面三种情况。
<union*M*,*N*>
:表示多个表的union
,其中M和N分别为第一列的id
<derived*N*>
:表示来自于其他表的衍生表,同上,M和N表示第一列的id
,通常,衍生表来自于from
语句后面的select
<subquery*N*>
: 表示物化后的子查询,N为第一列的id
。partitions
对于有分区的表该列有效
type
即join type
,分别有常见的system``, const, eq_ref, ALL
等, 下一节将详细介绍。
possible_keys
表示待选的索引
key
表示实际上用到的索引,来自于possible_keys
,当possible_keys
不为NULL
的时候,该列也有可能为none
,因为有时候用索引的效率不定义会比扫表高。
key_len
Mysql决定使用索引的长度(哪些部分),当一列有可能为NULL
的时候,key_len
的长度可能比该列大。
ref
表示用来和索引比较的常量或者某一列。
rows, filtered
rows
表示Mysql预估将要扫描的行数,filtered
表示Mysql预估的能过滤的行数(这里值的是返回给用户的行数),比如rows为100, filtered为70%,那么Mysql预估返回给用户70行数据。
Extra
表示Mysql解析一个query的一些额外信息,比如Using Index,Using filesort
等等。
对于type列,经常用于join
的场景,下面将根据效率由高到低进行说明:
system
const
的一种特殊情况,表示该表只有一行数据
const
表示只有最多只有一行匹配的数据,虽然该表可能有多行数据,但是对于和其join的表,其只需要一行数据,可以视作为const
,经常用于primary key
或者unique key
中,比如下面的语句:
SELECT * FROM tbl_name WHERE primary_key=1;
SELECT * FROM tbl_name
WHERE primary_key_part1=1 AND primary_key_part2=2;
eq_ref
Mysql可以使用索引进行equal操作,只适用于equal的情况,并且索引类型必须为primary key
或者unique not null
,在join的时候,这是除了system
和const
最好的情况。
ref
当一个索引不是primary key
或者unique index
的时候,又或者只能使用leftmost的时候,就会使用到ref
的情况,适用于=
或者<=>
fulltext
ref_or_null
和ref很像,但是除此之外,还需要额外寻找null字段,经常用于一些子查询的情况,比如下面的语句:
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
index_merge
表示会使用Section 8.2.1.3, “Index Merge Optimization”.技术进行优化
unique_subquery
和eq_ref
等价的情况,不过是针对于子查询的,譬如下面的语句:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
index_subquery
和unique_subquery
很像,不过是针对于子查询中的nonunique index
的,譬如下面的语句:
value IN (SELECT key_column FROM single_table WHERE some_expr)
range
一般索引的范围查找会用到,该种情况下,key
列表示所使用的索引,key_len
表示所使用的最长的key part,ref
是NULL
,适用于索引列和一个常量进行对比的情况,包括:=, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, LIKE, 或者IN
,譬如下面的语句:
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
,不过这种情况下是索引扫描,通常情况下,Extra
列为Using Index
ALL
最糟糕的情况,这种情况下只能进行全表扫描,此时应该考虑创建索引来加快join
的速度。
该小节省略,因为Extra
列的信息都比较易懂,碰到不清楚的可参考这里。
在EXPLAIN
之后,执行SHOW WARNINGS
命令,会看到EXPLAIN
的一些附加信息,在8.0.12
之后,该附加信息的适用条件为:SELECT, DELETE, INSERT, REPLACE和UPDATE
,在8.0.12
之前,该附加信息只有在SELECT
语句下才会产生,看下面的一个例子:
mysql> EXPLAIN
SELECT t1.a, t1.a IN (SELECT t2.a FROM t2) FROM t1\G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: t1
type: index
possible_keys: NULL
key: PRIMARY
key_len: 4
ref: NULL
rows: 4
filtered: 100.00
Extra: Using index
*************************** 2. row ***************************
id: 2
select_type: SUBQUERY
table: t2
type: index
possible_keys: a
key: a
key_len: 5
ref: NULL
rows: 3
filtered: 100.00
Extra: Using index
2 rows in set, 1 warning (0.00 sec)
mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a` AS `a`,
<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in
( <materialize> (/* select#2 */ select `test`.`t2`.`a`
from `test`.`t2` where 1 having 1 ),
<primary_index_lookup>(`test`.`t1`.`a` in
<temporary table> on <auto_key>
where ((`test`.`t1`.`a` = `materialized-subquery`.`a`))))) AS `t1.a
IN (SELECT t2.a FROM t2)` from `test`.`t1`
1 row in set (0.00 sec)
注意,可以看到这些查询语句可能会被重写,且包含特殊的标记符,所以这些语句不一定是合法的SQL
语句,该语句只是为了表示Mysql是如何具体来解析和执行的。
对于这些特殊的标记,部分解释如下:
<auto_key>
为临时自动生成的key
(expr)
表示该语句会被缓存在内存中,以后可能会使用到。
(query fragment)
表示语句被重写成了EXISTS
等等,还有很多,这里就不一一介绍了。
EXPLAIN FOR CONNECTION
语句用于一些性能诊断的情况,比如:一个session
执行的时间很长,那么可以在另外一个session
中使用该命令,指定特定的connection id
,那么就可以看到之所以执行这么长时间的额原因,该命令的格式如下:
EXPLAIN [options] FOR CONNECTION connection_id;
该命令适用于 SELECT
, DELETE
, INSERT
, REPLACE
, and UPDATE
. 但是,该命令不适用于任何prepared语句。
connection_id
是一个conection
的标识符,该id
可从 INFORMATION_SCHEMA
PROCESSLIST
table or the SHOW PROCESSLIST
statement中获取,但是使用者必须要有相关的权限,否则无法获取。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章