MySQL调优利器Explain
# 介绍
Expalin是用于获取SQL语句的执行计划的一个指令,比如是否走的索引,走的哪个索引之类的。
# 语法
官方定义语法:
{EXPLAIN | DESCRIBE | DESC}
表名 [col_name | wild]
{EXPLAIN | DESCRIBE | DESC}
[explain_type]
{explainable_stmt | FOR CONNECTION connection_id}
{EXPLAIN | DESCRIBE | DESC} ANALYZE [FORMAT = TREE] select_statement
explain_type: {
FORMAT = format_name
}
format_name: {
TRADITIONAL
| JSON
| TREE
}
explainable_stmt: {
SELECT statement
| TABLE statement
| DELETE statement
| INSERT statement
| REPLACE statement
| UPDATE statement
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
可以看出来,explain/desc/describe 三个有同样的功能,MySQL也把他们当作同义词,但是describe通常用来查询表结构,explain通常用来查询SQL执行的计划。
比如
# 表格形式显示结果
explain select * from xxxTable;
# json格式显示结果
explain FORMAT = JSON SELECT * FROM xxxTable;
# 分析SQL的执行时间与实际耗时
EXPLAIN ANALYZE SELECT * FROM xxxTable;
1
2
3
4
5
6
2
3
4
5
6
# 输出格式的解释
# 输出列的解释
行 | JSON Name | 含义 |
---|---|---|
id | select_id | 该SELECT标识符 |
select_type | None | 该SELECT类型 |
table | table_name | 操作的表 |
partitions | partitions | 匹配的分区 |
type | access_type | 联接类型 |
possible_keys | possible_keys | 可能的索引选择 |
key | key | 实际选择的索引 |
key_len | key_length | 所选键的长度 |
ref | ref | 与索引比较的列 |
rows | rows | 估计要检查的行数 |
filtered | filtered | 按表条件过滤的行百分比 |
Extra | None | 附加信息 |
注意:如果Format格式为JSON,那么不会显示为NULL的行
# select_type
select_type | JSON名称 | 含义 |
---|---|---|
simple | 没有 | 简单select(不使用 union或子查询) |
primary | 没有 | 最外层 select |
union | 没有 | 第二个或之后的select陈述 union |
dependent | union | dependent(true) |
union RESULT | union_result | 的结果union。 |
subquery | 没有 | 首先select在子查询 |
dependent subquery | dependent(true) | 首先select在子查询中,取决于外部查询 |
derived | 没有 | 派生表 |
dependent | derived dependent(true) | 派生表依赖于另一个表 |
materialized | materialized_from_subquery | 物化子查询 |
uncacheable subquery | cacheable(false) | 子查询,其结果无法缓存,必须针对外部查询的每一行重新进行评估 |
uncacheable union | cacheable(false) | union 属于不可缓存子查询的中的第二个或更高版本的选择(请参阅uncacheable subquery |
# type
- system:该表只有一行(=系统表)。这是const联接类型的特例 。
- const:该表最多具有一个匹配行,该行在查询开始时读取。因为只有一行,所以优化器的其余部分可以将这一行中列的值视为常量。 const表非常快,因为它们只能读取一次。比如我们通过唯一索引等值查询的时候就是const
- eq_ref:唯一索引单值扫描;
- ref:非唯一索引单值扫描;
- fulltext:使用FULLTEXT 索引执行联接。
- ref_or_null:这种连接类型类似于 ref,但是MySQL会额外搜索包含NULL值的行。此联接类型优化最常用于解析子查询。
- index_merge:此联接类型指示使用索引合并优化。在这种情况下,key输出行中的列包含使用的索引列表,并key_len包含使用的索引 的最长键部分的列表。
- unique_subquery:只是一个索引查找函数,它完全替代了子查询以提高效率,此类型替换以下形式的eq_ref某些IN子查询:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
1 - index_subquery:此连接类型类似于 unique_subquery。它替代IN子查询,但适用于以下形式的子查询中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
1 - range:命中where子句的范围索引扫描;
- index:走索引的全表扫描,当查询仅使用属于单个索引一部分的列时,MySQL可以使用此联接类型。两种方式:
- 如果索引是查询的覆盖索引,并且可用于满足表中所需的所有数据,则仅扫描索引树。在这种情况下,Extra列显示为 Using index。仅索引扫描通常比索引扫描更快, ALL因为索引的大小通常小于表数据。
- 使用对索引的读取执行全表扫描,以按索引顺序查找数据行。 Uses index没有出现在 Extra列中。
- all:全表扫描
# possible_keys
可能在哪个索引找到记录。
要查看表具有哪些索引,请使用。
SHOW INDEX FROM table_name
1
要强制MySQL使用或忽略列出的索引possible_keys列,使用 FORCE INDEX,USE INDEX或IGNORE INDEX在查询里。
SELECT * FROM table1 USE INDEX (col1_index,col2_index) WHERE col1=1 AND col2=2 AND col3=3;
SELECT * FROM table1 IGNORE INDEX (col3_index) WHERE col1=1 AND col2=2 AND col3=3;
1
2
3
2
3
# key
该key列指示MySQL实际决定使用的键(索引)。如果MySQL决定使用possible_keys 索引之一来查找行,则将该索引列为键值。
key中的值不一定会出现在possible_keys中,这个情况出现在查询的所有列都是其他索引的列。
select id from table;
1
比如这个情况下,即使没有使用索引当作查询条件,也会走索引。
# 参考
在 GitHub 编辑此页 (opens new window)
上次更新: 2024/02/25, 12:11:11