😇MySQLExplain使用教程

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317


61%

​Full scan on NULL key:子查询中的一种优化方式,在无法通过索引访问null值的时候使用

​Using Index:仅使用索引树中的信息从表中检索列信息,不用进行其他查找就可以读取实际行。(​覆盖索引:查询列都是索引列)

​No tables used:当此查询没有FROM子句或拥有FROM DUAL子句时出现。

​Impossible where:where子句始没有满足条件的目标数据,不会命中任何行

Using index condition:表示先按条件过滤索引,过滤完索引后找到所有符合索引条件的数据行,随后用 WHERE 子句中的其他条件去过滤这些数据行。(​使用索引范围查找,因查询列未被索引全覆盖,最终会回表查询。)

​Using join buffer:使用join buffer降低对被驱动表的扫描次数。

​Using where:不是读取表的所有数据或者不通过索引就可以获取所有需要的数据。(​未使用索引检索数据)

​Select tables optimized away:使用某些聚合函数(min,max)来访问某个索引值。(​无需查找表、索引就可以返回数据,效率非常高)

​Using filesort:当查询中包含 order by 操作而且无法利用索引完成的排序操作,数据较少时从内存排序,如果数据较多需要在磁盘中排序,需优化成索引排序。(​未使用索引进行排序导致在内存中或硬盘中排序)

​Using temporary:表示MySQL需要使用临时表来存储结果集;如果查询包含不同列的GROUP BY和 ORDER BY子句,通常会发生这种情况。(​使用临时表存储数据进行数据去重等操作)

可以通过添加索引的方式,优化成using index​

​Extra:SQL执行查询的一些额外信息。

​NULL:最后执行。且表示结果集,不需要使用它来进行查询

​id相同:执行顺序从上往下

​同时存在:先执行序号大,在从上往下

​id不同:序号大先执行

id:每个select都对应一个id,从1开始递增。如果该查询有子查询,将显示多个id值。

​filtered:表示符合查询条件的数据百分比。可以使用rows \* filtered/100计算出与explain前一个表进行连接的行数。

​rows:全表扫描时表示需要扫描表的行数估计值;索引扫描时表示扫描索引的行数估计值;值越小越好。

​UNCACHEABLE SUBQUERY:一个子查询的结果不能被缓存,而是需要每次查询时重新计算。

​SIMPLE:简单select,不包括union与子查询

​UNION RESULT:如果两个查询中有相同的列,则会对这些列进行重复删除,只保留一个表中的列。

​PRIMARY:复杂查询中最外层查询,比如使用union或union all时,id为1的记录select\_type通常是primary

​DEPENDENT UNION:当union作为子查询时,其中第一个union为dependent subquery,第二个union为dependent union。

SUBQUERY:指在 select 语句中出现的查询语句,结果不依赖于外部查询

​UNION:分union与union all两种,id大于1的select被标记为union;如果union被from子句的子查询包含,那么第一个select会被标记为derived;union会针对相同的结果集进行去重,union all不会进行去重处理。

​DEPENDENT SUBQUERY:指在 select 语句中出现的查询语句,结果依赖于外部查询

​DERIVED:派生表,在FROM子句的查询语句,表示从外部数据源中推导出来的,而不是从 SELECT 语句中的其他列中选择出来的。

select\_type:查询类型。

​ref:表示将哪个字段或常量和key列所使用的字段进行比较。

​如果有别名,展示别名。

​如果有多个表,将显示多行记录。

table:查询所涉及的表名。

​partitions:表分区情况。

​字段如果为NULL,需要1个字节记录是否为NULL(空值字段:1字节)

​varchar(n):如果是uft-8:3n+2字节,加的2个字节存储字符串长度。如果是utf8mb4:4n+2 字节(变长字段:2字节)

​char(n):n个字节

​字符串

​datetime:8字节

​date:3字节

​ timestamp:4字节 

​时间类型

​ bigint:8字节

​ tinyint:1字节

​ int:4字节

​smaillint:2字节

​数值类型

​计算规则

​作用:使用联合索引的时候可以知道使用了哪几列

​key\_len:表示当优化器决定使用某个索引执行查询时,该索引记录的最大长度。

​key:表示实际在查询中使用的索引,如果没有使用索引,显示NULL。

​possible\_keys:表示在查询中可能使用到某个索引或多个索引;如果没有选择索引,显示NULL。

all:扫描整个表进行匹配

避免使用

很少出现

​NULL:MySQL在优化过程中分解语句就已经可以获取到结果,执行时甚至不用访问表或索引,效率高

index:扫描整个索引进行匹配

​system:const类型的一种特殊场景,查询的表只有一行的情况

range:使用非唯一索引扫描部分索引,比如使用索引获取某些范围区间的记录

​index\_subquery:查询使用子查询的索引,当查询需要过滤大量数据时,使用子查询可以提高查询效率,而使用索引可以提高查询性能。

const:基于主键或唯一索引查看一行,当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问转换成常量查询,效率高

eq\_ref:基于主键或唯一索引连接两个表,对于每个索引键值,只有一条匹配记录

​unique\_subquery:查询使用合并索引来执行,当查询需要过滤大量数据时,使用子查询可以避免重复行,从而提高查询效率。

ref:基于非唯一索引连接两个表,通过二级索引列与常量进行等值匹配,可能会存在多条匹配记录

​index\_merge:表示使用了索引合并的优化方法,当查询需要扫描大量的数据时,使用合并索引可以提高查询效率。

​fulltext:全文索引

​ref\_or\_null:基于非唯一索引连接两个表,通过二级索引进行等值匹配询,该索引列的值可以是NULL值。

推荐使用​

​type:查询所使用的访问类型。(查询效率从上往下依次递减)

​Explain返回列详解

​Explain含义:Explain是 SQL 分析工具中非常重要的一个功能,它可以模拟优化器执行查询语句,帮助我们理解查询是如何执行的;分析查询执行计划可以帮助我们发现查询瓶颈,优化查询性能。

与​show warnings搭配使用查看执行器优化后的SQL:

Explain select \* from student;

show warnings;

​MySQL5.7版本之前使用Explain Extended关键字:Explain Extended select \* from student;

​MySQL5.7版本开始使用Explain关键字:Explain select \* from student;

​Explain使用方法

Explain使用与详解​

Explain使用与详解​

​Explain含义:Explain是 SQL 分析工具中非常重要的一个功能,它可以模拟优化器执行查询语句,帮助我们理解查询是如何执行的;分析查询执行计划可以帮助我们发现查询瓶颈,优化查询性能。

​Explain使用方法

​MySQL5.7版本之前使用Explain Extended关键字:Explain Extended select \* from student;

​MySQL5.7版本开始使用Explain关键字:Explain select \* from student;

与​show warnings搭配使用查看执行器优化后的SQL:

Explain select \* from student;

show warnings;

​Explain返回列详解

id:每个select都对应一个id,从1开始递增。如果该查询有子查询,将显示多个id值。

​id相同:执行顺序从上往下

​id不同:序号大先执行

​同时存在:先执行序号大,在从上往下

​NULL:最后执行。且表示结果集,不需要使用它来进行查询

select\_type:查询类型。

​SIMPLE:简单select,不包括union与子查询

​PRIMARY:复杂查询中最外层查询,比如使用union或union all时,id为1的记录select\_type通常是primary

SUBQUERY:指在 select 语句中出现的查询语句,结果不依赖于外部查询

​DEPENDENT SUBQUERY:指在 select 语句中出现的查询语句,结果依赖于外部查询

​DERIVED:派生表,在FROM子句的查询语句,表示从外部数据源中推导出来的,而不是从 SELECT 语句中的其他列中选择出来的。

​UNION:分union与union all两种,id大于1的select被标记为union;如果union被from子句的子查询包含,那么第一个select会被标记为derived;union会针对相同的结果集进行去重,union all不会进行去重处理。

​DEPENDENT UNION:当union作为子查询时,其中第一个union为dependent subquery,第二个union为dependent union。

​UNION RESULT:如果两个查询中有相同的列,则会对这些列进行重复删除,只保留一个表中的列。

​UNCACHEABLE SUBQUERY:一个子查询的结果不能被缓存,而是需要每次查询时重新计算。

table:查询所涉及的表名。

​如果有多个表,将显示多行记录。

​如果有别名,展示别名。

​partitions:表分区情况。

​type:查询所使用的访问类型。(查询效率从上往下依次递减)

​NULL:MySQL在优化过程中分解语句就已经可以获取到结果,执行时甚至不用访问表或索引,效率高

​system:const类型的一种特殊场景,查询的表只有一行的情况

const:基于主键或唯一索引查看一行,当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问转换成常量查询,效率高

eq\_ref:基于主键或唯一索引连接两个表,对于每个索引键值,只有一条匹配记录

ref:基于非唯一索引连接两个表,通过二级索引列与常量进行等值匹配,可能会存在多条匹配记录

​fulltext:全文索引

​ref\_or\_null:基于非唯一索引连接两个表,通过二级索引进行等值匹配询,该索引列的值可以是NULL值。

​index\_merge:表示使用了索引合并的优化方法,当查询需要扫描大量的数据时,使用合并索引可以提高查询效率。

​unique\_subquery:查询使用合并索引来执行,当查询需要过滤大量数据时,使用子查询可以避免重复行,从而提高查询效率。

​index\_subquery:查询使用子查询的索引,当查询需要过滤大量数据时,使用子查询可以提高查询效率,而使用索引可以提高查询性能。

range:使用非唯一索引扫描部分索引,比如使用索引获取某些范围区间的记录

index:扫描整个索引进行匹配

all:扫描整个表进行匹配

很少出现

推荐使用​

避免使用

​possible\_keys:表示在查询中可能使用到某个索引或多个索引;如果没有选择索引,显示NULL。

​key:表示实际在查询中使用的索引,如果没有使用索引,显示NULL。

​key\_len:表示当优化器决定使用某个索引执行查询时,该索引记录的最大长度。

​作用:使用联合索引的时候可以知道使用了哪几列

​计算规则

​字符串

​char(n):n个字节

​varchar(n):如果是uft-8:3n+2字节,加的2个字节存储字符串长度。如果是utf8mb4:4n+2 字节(变长字段:2字节)

​数值类型

​ tinyint:1字节

​smaillint:2字节

​ int:4字节

​ bigint:8字节

​时间类型

​date:3字节

​ timestamp:4字节 

​datetime:8字节

​字段如果为NULL,需要1个字节记录是否为NULL(空值字段:1字节)

​ref:表示将哪个字段或常量和key列所使用的字段进行比较。

​rows:全表扫描时表示需要扫描表的行数估计值;索引扫描时表示扫描索引的行数估计值;值越小越好。

​filtered:表示符合查询条件的数据百分比。可以使用rows \* filtered/100计算出与explain前一个表进行连接的行数。

​Extra:SQL执行查询的一些额外信息。

​Using Index:仅使用索引树中的信息从表中检索列信息,不用进行其他查找就可以读取实际行。(​覆盖索引:查询列都是索引列)

Using index condition:表示先按条件过滤索引,过滤完索引后找到所有符合索引条件的数据行,随后用 WHERE 子句中的其他条件去过滤这些数据行。(​使用索引范围查找,因查询列未被索引全覆盖,最终会回表查询。)

​Using where:不是读取表的所有数据或者不通过索引就可以获取所有需要的数据。(​未使用索引检索数据)

​Using temporary:表示MySQL需要使用临时表来存储结果集;如果查询包含不同列的GROUP BY和 ORDER BY子句,通常会发生这种情况。(​使用临时表存储数据进行数据去重等操作)

​Using filesort:当查询中包含 order by 操作而且无法利用索引完成的排序操作,数据较少时从内存排序,如果数据较多需要在磁盘中排序,需优化成索引排序。(​未使用索引进行排序导致在内存中或硬盘中排序)

​Select tables optimized away:使用某些聚合函数(min,max)来访问某个索引值。(​无需查找表、索引就可以返回数据,效率非常高)

​Using join buffer:使用join buffer降低对被驱动表的扫描次数。

​Impossible where:where子句始没有满足条件的目标数据,不会命中任何行

​No tables used:当此查询没有FROM子句或拥有FROM DUAL子句时出现。

​Full scan on NULL key:子查询中的一种优化方式,在无法通过索引访问null值的时候使用

可以通过添加索引的方式,优化成using index​


1.Explain含义

Explain是 SQL 分析工具中非常重要的一个功能,它可以模拟优化器执行查询语句,帮助我们理解查询是如何执行的;分析查询执行计划可以帮助我们发现查询瓶颈,优化查询性能。

2.Explain作用

●表的读取顺序
●SQL执行时查询操作类型
●可以使用哪些索引
●实际使用哪些索引
●每张表有多少行记录被扫描
●SQL语句性能分析

3.Explain用法

1
2
3



MySQL5.7版本之前,使用Explain Extended在Explain的基础上额外多返回filtered列与extra列;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


Explain Extended select \* from users;












MySQL5.7版本之前,使用Explain Partitions在Explain的基础上额外多返回partitions列;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


Explain Partitions select \* from users;












MySQL5.7版本引入了这两个特性,直接使用Explain关键字可以将partitions列、filtered列、extra列直接查询出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15


Explain select \* from users;












Explain语句返回列的各列含义:

列名

含义

id

每个select都有一个对应的id号,并且是从1开始自增的

select_type

查询语句执行的查询操作类型

table

表名

partitions

表分区情况

type

查询所用的访问类型

possible_keys

可能用到的索引

key

实际查询用到的索引

key_len

所使用到的索引长度

ref

使用到索引时,与索引进行等值匹配的列或者常量

rows

预计扫描的行数(索引行数或者表记录行数)

filtered

表示符合查询条件的数据百分比

Extra

SQL执行的额外信息

这些查询列大家先留一个印象,后续会详细讲解。

4.Explain返回列详解

接下来我们将展示Explain中每个列的信息

1. id列:每个select都有一个对应的id号,并且是从1开始自增的。

●如果id序号相同,从上往下执行。
●如果id序号不同,序号大先执行。
●如果两种都存在,先执行序号大,在同级从上往下执行。
●如果显示NULL,最后执行。表示结果集,并且不需要使用它来进行查询。

优化器会针对子查询进行一定的优化重写SQL:

2.select_type列:表示查询语句执行的查询操作类型

2.1.simple:简单select,不包括union与子查询
2.2.primary:复杂查询中最外层查询,比如使用union或union all时,id为1的记录select_type通常是primary
2.3.subquery:指在 select 语句中出现的子查询语句,结果不依赖于外部查询(不在from语句中)
2.4.dependent subquery:指在 select 语句中出现的查询语句,结果依赖于外部查询
2.5.derived:派生表,在FROM子句的查询语句,表示从外部数据源中推导出来的,而不是从 SELECT 语句中的其他列中选择出来的。
2.6.union:分union与union all两种,若第二个select出现在union之后,则被标记为union;如果union被from子句的子查询包含,那么第一个select会被标记为derived;union会针对相同的结果集进行去重,union all不会进行去重处理。
2.7.dependent union:当union作为子查询时,其中第一个union为dependent subquery,第二个union为dependent union。
2.8.union result:如果两个查询中有相同的列,则会对这些列进行重复删除,只保留一个表中的列。

3.table列:查询所涉及的表名。如果有多个表,将显示多行记录

4.partitions列:表分区情况

查询语句所涉及的表的分区情况。具体来说,它会显示出查询语句在哪些分区上执行,以及是否使用了分区裁剪等信息。如果没有分区,该项为NULL。

5.type列:查询所使用的访问类型

效率从高到低分别为:system > const > eq_ref > ref > fulltext > ref_or_null > range > index > ALL,一般来说保证range级别,最好能达到ref级别。

5.1.system:const类型的一种特殊场景,查询的表只有一行记录的情况,并且该表使用的存储引擎的统计数据是精确的

InnoDb存储引擎的统计数据不是精确的,虽然只有一条数据但是type类型为ALL;

Memory存储引擎的统计数据是精确的,所以当只有一条记录的时候type类型为system。

5.2.const:基于主键或唯一索引查看一行,当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问转换成常量查询,效率高
5.3.eq_ref:基于主键或唯一索引连接两个表,对于每个索引键值,只有一条匹配记录,被驱动表的类型为’eq_ref’
5.4.ref:基于非唯一索引连接两个表或通过二级索引列与常量进行等值匹配,可能会存在多条匹配记录

1.关联查询,使用非唯一索引进行匹配。
2.简单查询,使用二级索引列匹配。

5.5.range:使用非唯一索引扫描部分索引,比如使用索引获取某些范围区间的记录
5.6.index:扫描整个索引就能拿到结果,一般是二级索引,这种查询一般为使用覆盖索引(需优化,缩小数据范围)
5.7.all:扫描整个表进行匹配,即扫描聚簇索引树(需优化,添加索引优化)
5.8.NULL:MySQL在优化过程中分解语句就已经可以获取到结果,执行时甚至不用访问表或索引。

6.possible_keys列:表示在查询中可能使用到某个索引或多个索引;如果没有选择索引,显示NULL

7.key列:表示在查询中实际使用的索引,如果没有使用索引,显示NULL。

8.key_len列:表示当优化器决定使用某个索引执行查询时,该索引记录的最大长度(主要使用在联合索引)

联合索引可以通过这个值算出具体使用了索引中的哪些列。
使用单例索引:

使用联合索引:

计算规则:
●字符串:
char(n):n个字节 varchar(n):如果是uft-8:3n+2字节,加的2个字节存储字符串长度。如果是utf8mb4:4n+2字节。
●数值类型:
tinyint:1字节
smaillint:2字节
int:4字节
bigint:8字节
●时间类型:
date:3字节
timestamp:4字节
datetime:8字节 字段如果为NULL,需要1个字节记录是否为NULL

9.ref列:表示将哪个字段或常量和key列所使用的字段进行比较。

当使用索引列等值查询时,与索引列进行等值匹配的对象信息。
1.常量:

2.字段:

3.函数

10.rows列:全表扫描时表示需要扫描表的行数估计值;索引扫描时表示扫描索引的行数估计值;值越小越好(不是结果集中的行数)

1.全表扫描

2.索引扫描

11.filtered列:表示符合查询条件的数据百分比。可以使用rows * filtered/100计算出与explain前一个表进行连接的行数。

前一个表指 explain 中的id值比当前表id值小的表,id相同的时候指后执行的表。

12.Extra列:SQL执行查询的一些额外信息

12.1.Using Index:使用非主键索引树就可以查询所需要的数据。一般是覆盖索引,即查询列都包含在辅助索引树叶子节点中,不需要回表查询。
12.2.Using where:不通过索引查询所需要的数据
12.3.Using index condition:表示查询列不被索引覆盖,where 条件中是一个索引范围查找,过滤完索引后回表找到所有符合条件的数据行。
12.4.Using temporary:表示需要使用临时表来处理查询;

1.total_price列无索引,需要创建一张临时表进行去重

2.name列有联合索引

12.5.Using filesort:当查询中包含 order by 操作而且无法利用索引完成的排序操作,数据较少时从内存排序,如果数据较多需要在磁盘中排序。 需优化成索引排序。

1.total_price列无索引,无法通过索引进行排序。需要先保存total_price与对应的主键id,然后在排序total_price查找数据。

2.name列有索引,因索引已经是排好序的所以直接读取就可以了。

12.6.Select tables optimized away:使用某些聚合函数(min,max)来访问某个索引值。

5. 总结

正确合理使用 MySQL explain 可以帮助我们更好地理解查询执行计划,并确定如何最好地优化查询SQL,提升SQL性能,增加系统稳定性。