Explain
查看执行计划,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。
官方文档
适用范围:SELECT
, DELETE
, INSERT
, REPLACE
,和 UPDATE
语句。
一、id
Select 查询中的序列号,表示查询中执行Select 的顺序或者操作表的顺序
-
id相同从上至下顺序执行。
执行顺序:T1,T2
-
id不同,id的序号会递增,id值大的先执行。
执行顺序:T2,T1
-
id有相同有不同的情况下,id 大的先执行,id相同的从上到下执行
执行顺序:T3,T1,T2
二、select_type
查询类型,主要用于区分普通查询、联合查询、子查询等
select_type类型
select_type Value |
JSON Name | Meaning |
---|---|---|
SIMPLE |
None | 简单的查询(不使用UNION或者子查询) |
PRIMARY |
None | 最外层的Select |
UNION |
None | 若第二个Select出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句中,外层Select将被标记为:DERIVED |
DEPENDENT UNION |
dependent (true ) |
在UNION中第二个或以后的Select语句,依赖于外部查询 |
UNION RESULT |
union_result |
从UNION中获取表的结果的Select |
SUBQUERY |
None | 子查询 |
DEPENDENT SUBQUERY |
dependent (true ) |
依赖于外部查询的子查询 |
DERIVED |
None | 派生表(临时表) |
DEPENDENT DERIVED |
dependent (true ) |
派生表依赖于另一个表 |
MATERIALIZED |
materialized_from_subquery |
物化子查询 |
UNCACHEABLE SUBQUERY |
cacheable (false ) |
无法缓存结果并且必须为外部查询的每一行重新评估的子查询 |
UNCACHEABLE UNION |
cacheable (false ) |
UNION 属于不可缓存子查询的第二个或以后的选择 |
-
SIMPLE
-
PRIMARY
-
UNION
-
UNION RESULT
-
SUBQUERY
三、table
输出行所引用的表的名称,表名
四、type
访问类型,
从最好类型到最差类型:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > all
常用的从最好类型到最差类型:
system > const > eq_ref > ref > range > index > all
-
system
该表只有一行(= 系统表)。这是
const
连接类型的一个特例 。 -
const
该表最多有一个匹配行,在查询开始时读取。因为只有一行,该行中该列的值可以被优化器的其余部分视为常量。
const
表非常快,因为它们只被读取一次。MySQL就能将查询转换为一个常量。SELECT * FROM tbl_name WHERE primary_key=1; SELECT * FROM tbl_name WHERE primary_key_part1=1 AND primary_key_part2=2;
-
eq_ref
唯一性索引扫描,对于每个索引键,表中只有一条记录与之对应。常见于主键或唯一索引扫描。
当连接使用索引的所有部分并且索引是一个
PRIMARY KEY
或UNIQUE NOT NULL
索引时使用它。eq_ref
可用于使用=
运算符进行比较的索引列 。比较值可以是常量或表达式,该表达式使用在此表之前读取的表中的列。在以下示例中,MySQL 可以使用eq_ref
连接来处理ref_table
: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
如果联接仅使用键的最左边前缀,或者该键不是PRIMARY key或UNIQUE索引(换句话说,如果连接不能根据键值选择单行),则使用ref。如果所使用的键只匹配少数行,那么这是一种很好的连接类型。
ref
可用于使用=
or<=>
运算符进行比较的索引列 。在以下示例中,MySQL 可以使用ref
连接来处理ref_table
: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
索引执行的。 -
ref_or_null
这种连接类型类似于
ref
,但另外,MySQL 会额外搜索包含NULL
值的行。这种连接类型优化最常用于解析子查询。在以下示例中,MySQL 可以使用ref_or_null
连接来处理ref_table
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
-
index_merge
此连接类型表示使用了索引合并优化。在这种情况下,
key
输出行中的列包含所使用索引的列表,并key_len
包含所使用索引 的最长关键部分的列表。where 条件后可能有多个条件(或者 join )涉及到多个字段,他们之间进行 AND 或 OR,那么此时就有可能会用到 index_merge 技术; index_merge 技术如果简单的说就是:对多个索引分别进行条件扫描,然后将各自的结果进行合并(intersect/union)
-
unique_subquery
这种类型替代 了以下形式的
eq_ref
一些IN
子查询:value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery
只是一个索引查找函数,完全替换子查询以提高效率。 -
index_subquery
这种联接类型类似于
unique_subquery
. 它取代了IN
子查询,但它适用于以下形式的子查询中的非唯一索引:value IN (SELECT key_column FROM single_table WHERE some_expr)
-
range
只检索给定范围内的行,使用索引选择行。输出行中的键列指示使用哪个索引。key_len包含所使用的最长的密钥部分。对于这种类型,ref列是NULL。
range
当使用=
,<>
,>
,>=
,<
,<=
,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
该
index
联接类型是一样的ALL
,只是索引树被扫描。这有两种方式:- 如果索引是查询的覆盖索引,并且可以用来满足表中所需的所有数据,则只扫描索引树。在本例中,Extra列显示Using index。仅索引扫描通常比ALL扫描快,因为索引的大小通常小于表数据。
- 全表扫描是通过从索引中读取数据以按照索引顺序查找数据行来执行的。
Uses index
不会出现在Extra
列中。
当查询仅使用属于单个索引的列时,MySQL 可以使用此连接类型。
-
ALL
对先前表中的每个行组合进行全表扫描。如果该表是第一个未标记的表
const
,这通常不好,并且在所有其他情况下通常 非常糟糕。通常,您可以ALL
通过添加索引来避免 基于常量值或早期表中的列值从表中检索行。
五、possible_keys
显示可能应用在这张表的索引,一个或多个。
查询涉及到的字段上若存在索引,则该索引被列出。但是不一定被查询实际使用。
如果此列是NULL
(或在 JSON 格式的输出中未定义),则没有相关索引。在这种情况下,您可以通过检查WHERE
子句来检查它是否引用了适合编制索引的某些列或多列,从而提高查询的性能
六、key
该
key
列表示 MySQL 实际决定使用的键(索引),如果为 null,则没有用到索引。
查询中如果使用到了覆盖索引,则该索引仅出现在key列表中。
七、key_len
key_len表示使用的索引长度[字节数],key_len可以衡量索引的好坏,key_len越小 索引效果越好。
八、ref
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。
九、rows
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数
对于
InnoDB
表格,这个数字是一个估计值,可能并不总是准确的。
十、Extra
包含不适合在其他列中显示但十分重要的额外信息
-
Using filesort (影响性能)
MySQL 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。
MySQL中无法利用索引完成的排序操作称为 “文件排序”。
-
未使用文件排序情况
-
使用文件排序情况
-
-
Using temporary (影响性能)
使用了临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。
该表存在的索引
查看执行计划【用到了Using temporary】
查看执行计划【未用到Using temporary】,尽量按照索引顺序来,防止文件内排序。
-
Using index (表示使用到了索引覆盖)
表示相应的Select 操作使用到了索引覆盖(Covering Index ),避免访问了表的数据行,效率不错!
-
如果同时出现 Using Where,表明索引被用来执行索引键值的查找。
-
如果没有同时出现Using Where ,表明索引用来读取数据而非执行查找动作。
-
-
Using where
表明使用了where过滤
产生情况案例:
-
Using join buffer
使用了连接缓存
连接的表被读入连接缓冲区,然后它们的行从缓冲区中用于执行与当前表的连接。
-
Impossible WHERE
MySQL 已读取所有
const
(和system
)表并注意到该WHERE
子句始终为假。产生情况案例: