MySQL优化正餐之_EXPLAIN执行计划
2019-08-11 20:51:43 215 举报
AI智能生成
MySQL优化正餐之_EXPLAIN执行计划
作者其他创作
大纲/内容
本次案例使用到的SQL
使用方式
在查询语句前面加上EXPLAIN关键字
<font color="#c41230">EXPLAIN</font> SELECT * FROM tablename;
各字段含义
id
在一个大的查询语句中<font color="#c41230">每个SELECT</font>关键字都对应一个<font color="#c41230">唯一的ID</font>
select_type
SELECT关键字对应的那个查询的类型
type
单表访问的方法
table
表名
partitions
匹配的分区信息(暂时不涉及)
possible_keys
可能用到的索引
key
实际上使用的索引
key_len
实际使用到的索引长度
ref
当使用索引列等值查询时,与索引列进行等值匹配的对象信息<br>比如常量const,函数func,或者是驱动表的主键
rows
预估的需要读取的记录数
filtered
某个表经过搜索条件过滤后剩余记录条数的百分比<br>(扇出率)
Extra
一些额外信息
id列详解
查询语句中每出现一个SELECT关键字,MySQL就会为它分配一个唯一的ID值
注意点
对于连接查询来说,一个SELECT关键字后边的FROM子句中可以跟随多个表,<br>所以在<font color="#c41230">连接查询</font>的执行计划中,每个表都会对应一条记录,<font color="#c41230">但是这些记录的id值都是相同的</font>
在连接查询的执行计划中,每个表都会对应一条记录,这些记录的id列的值是相同的,<br><font color="#c41230">出现在前边的表表示驱动表,出现在后边的表表示被驱动表。</font>
<font color="#c41230">查询优化器可能对涉及子查询的查询语句进行重写,从而转换为连接查询。</font><br><font color="#381e11">那么这时候他们的ID值就一样了啦</font>
对于UNION查询产生的临时表的表示
select_type列详解
取值范围
各取值范围详解
SIMPLE
查询语句中不包含UNION或者子查询的查询
当然连接查询也算是SIMPLE类型
PRIMARY
对于包含UNION、UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,<br>其中最左边的那个查询的select_type值就是PRIMARY
英文解释直译过来也是 最外层的查询
UNION
对于包含UNION或者UNION ALL的大查询来说,它是由几个小查询组成的,<br>其中除了最左边的那个小查询以外,其余的小查询的select_type值就是UNION
UNION_RESULT
MySQL选择使用<font color="#c41230">临时表来完成UNION查询的去重工作</font>,<br>针对该临时表的查询的select_type就是UNION RESULT
SUBQUERY
如果包含子查询的查询语句不能够转为对应的<font color="#c41230">semi-join</font>的形式,并且该子查询是<font color="#c41230">不相关子查询</font>,并且查询优化器决定采用<font color="#c41230">将该子查询物化的方案</font>来执行该子查询时,该子查询的<font color="#c41230">第一个SELECT关键字</font>代表的那个查询的select_type就是SUBQUERY
<font color="#c41230">由于select_type为SUBQUERY的子查询由于会被物化,所以只需要执行一遍</font>
DEPENDENT SUBQUERY
如果包含子查询的查询语句不能够转为对应的semi-join的形式,并且该子查询是相关子查询,<br>则该子查询的第一个SELECT关键字代表的那个查询的select_type就是DEPENDENT SUBQUERY
<font color="#c41230">select_type为DEPENDENT SUBQUERY的查询可能会被执行多次。</font>
DEPENDENT UNION
在包含UNION或者UNION ALL的大查询中,如果各个小查询都依赖于外层查询的话,<br>那<font color="#c41230">除了最左边的那个小查询之外,其余的小查询</font>的select_type的值就是DEPENDENT UNION。
DERIVED
对于采用<font color="#c41230">物化</font>的方式执行的包含<font color="#c41230">派生表</font>的查询,该派生表对应的子查询的select_type就是DERIVED
MATERIALIZED
当查询优化器在执行包含子查询的语句时,选择<font color="#c41230">将子查询物化之后与外层查询进行连接查询时</font>,<br>该子查询对应的select_type属性就是MATERIALIZED
UNCACHEABLE SUBQUERY
并不常用
UNCACHEABLE UNION
并不常用
table列详解
查询哪个表
partitions列详解
暂时用不上
type列详解
取值范围
system
<font color="#c41230">当表中只有一条记录</font>并且该表使用的<font color="#c41230">存储引擎的统计数据是精确的,比如MyISAM、Memory</font>,那么对该表的访问方法就是system。
当表中只有一条记录并且该表使用的存储引擎的统计数据是<font color="#c41230">不精确</font>的,比如<font color="#c41230">InnoDB</font>,那么对该表的访问方法就是<font color="#c41230">全表扫描</font>。
const
根据<font color="#c41230">主键或者唯一二级索引列</font>与<font color="#c41230">常数</font>进行<font color="#c41230">等值匹配</font>时,对单表的访问方法就是const
eq_ref
在<font color="#c41230">连接查询</font>时,如果<font color="#c41230">被驱动表</font>是通过<font color="#c41230">主键或者唯一二级索引列等值匹配</font>的方式进行访问的(<font color="#c41230">如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较</font>),则对该被驱动表的访问方法就是eq_ref
ref
当通过<font color="#c41230">普通的二级索引列与常量进行等值匹配</font>时来查询某个表,那么对该表的访问方法就可能是ref
ref_or_null
当对<font color="#c41230">普通二级索引进行等值匹配查询,该索引列的值也可以是NULL值</font>时,那么对该表的访问方法就可能是ref_or_null
index_merge
使用Intersection、Union、Sort-Union这三种<font color="#c41230">索引合并</font>的方式来执行查询
unique_subquery
类似于两表连接中被驱动表的eq_ref访问方法,unique_subquery是<font color="#c41230">针对在一些包含IN子查询的查询语句中</font>,如果查询优化器决定<font color="#c41230">将IN子查询转换为EXISTS子查询</font>,而且<font color="#c41230">子查询可以使用到主键进行等值匹配</font>的话,那么该子查询执行计划的type列的值就是unique_subquery
index_subquery
index_subquery与unique_subquery类似,只不过访问<font color="#c41230">子查询中的表时使用的是普通的索引</font>,比如这样:
range
如果<font color="#c41230">使用索引获取某些范围区间的记录</font>,那么就可能使用到range访问方法
index
当我们可以使用<font color="#c41230">索引覆盖</font>,但需要<font color="#c41230">扫描全部的索引记录</font>时,该表的访问方法就是index
ALL
熟悉的全表扫描
fulltext
全文索引,支持一般,专业人干专业事,建议上ES或者Solr
possible_keys与key列详解
possible_keys列表示在某个查询语句中,对某个表执行单表查询时<font color="#c41230">可能用到的索引</font>有哪些,key列表示<font color="#c41230">实际用到的索引</font>有哪些
key_len列详解
key_len列表示当优化器决定使用某个索引执行查询时,该索引记录的<font color="#c41230">最大长度</font>
作用
在使用<font color="#c41230">联合索引</font>的时候就可以知道用了哪几列啦
计算规则
对于使用固定长度类型的索引列来说,它实际占用的存储空间的最大长度就是该固定值,对于指定字符集的变长类型的索引列来说,比如某个索引列的类型是VARCHAR(100),使用的字符集是utf8,那么该列实际占用的最大存储空间就是100 × 3 = 300个字节。
如果该索引列可以存储NULL值,则key_len比不可以存储NULL值时多1个字节。
对于变长字段来说,都会有2个字节的空间来存储该变长列的实际长度。
举一个栗子
ref列详解
ref列展示的就是<font color="#c41230">与索引列作等值匹配的东东是个啥</font>,<font color="#c41230">比如只是一个常数或者是某个列</font>。
常数const的栗子
某一列的栗子
函数func的栗子
rows列详解
如果查询优化器决定使用<font color="#c41230">全表扫描</font>的方式对某个表执行查询时,执行计划的rows列就代表<font color="#c41230">预计需要扫描的行数</font>,<br>如果使用<font color="#c41230">索引</font>来执行查询时,执行计划的rows列就<font color="#c41230">代表预计扫描的索引记录行数</font>。
filtered列详解
驱动表扇出的比例,当然是越低越好啦
Extra列详解
常见取值
No tables used
当查询语句的没有FROM子句时将会提示该额外信息
Impossible WHERE
查询语句的WHERE子句永远为FALSE时将会提示该额外信息
No matching min/max row
当查询列表处有MIN或者MAX聚集函数,但是并<font color="#c41230">没有符合WHERE子句中的搜索条件的记录</font>时,将会提示该额外信息
Using index
<span style="font-size: inherit;">当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在<font color="#c41230">可以使用索引覆盖(bu)</font>的情况下,在Extra列将会提示该额外信息</span><br>
Using index condition
如果在查询语句的执行过程中将要使用<font color="#c41230">索引条件下推</font>这个特性,在Extra列中将会显示Using index condition
什么是索引下推
SELECT * FROM s1 WHERE key1 > 'z' AND key1 LIKE '%a';
对于上面的这条SQL语句,因为这时候走的是以range访问方式走的key1索引。<br><font color="#c41230">而key1 LIKE '%a'由于不满足前缀匹配,所以需要回表访问的时候再过滤</font>
可是这个条件列又刚好是key1索引列。<font color="#c41230">如果在二级索引的时候,就进行过滤条件判断,不放到回表后判断。<br>那么就可以减少回表访问的次数,也就是减少随机IO的发生</font>。
所以把<font color="#c41230">【如果在二级索引的时候,就进行过滤条件判断,不放到回表后判断 】</font>这种情况叫做索引下推
Using where
当我们使用<font color="#c41230">全表扫描</font>来执行对某个表的查询,并且该语句的<font color="#c41230">WHERE子句中有针对该表的搜索条件时</font>
当使用<font color="#c41230">索引访问</font>来执行对某个表的查询,并且该语句的WHERE子句中有<font color="#c41230">除了该索引包含的列之外的其他搜索条件时</font>,在Extra列中也会提示上述额外信息。
Using join buffer (Block Nested Loop)
使用JOIN BUFFER来降低被驱动表的访问次数从而提高查询效率
Not exists
当我们使用左(外)连接时,如果WHERE子句中包含要求<font color="#c41230">被驱动表的某个列等于NULL值</font>的搜索条件<font color="#c41230">,而且那个列又是不允许存储NULL值的</font>,那么在该表的执行计划的Extra列就会提示Not exists额外信息. (也就是如果在被驱动表中匹配到一条记录,那么就<font color="#c41230">不再往下走了</font>)
Using intersect(...)、Using union(...)和Using sort_union(...)
使用到索引合并的时候就会有这种情况啦
Zero limit
当我们的LIMIT子句的参数为0时
Using filesort
不根据所以树进行排序,而在内存中或者磁盘上进行排序的方式统称为文件排序(英文名:filesort)
Using temporary
在许多查询的执行过程中,MySQL可能会借助<font color="#c41230">临时表</font>来完成一些功能,比如<font color="#c41230">去重、排序</font>之类的,比如我们在执行许多包含<font color="#c41230">DISTINCT、GROUP BY、UNION</font>等子句的查询过程中,如果不能有效利用索引来完成查询,MySQL很有可能寻求通过建立内部的临时表来执行查询。
DISTINCT的栗子
Group by 的栗子
Start temporary, End temporary
查询优化器会优先尝试将IN子查询转换成semi-join,而<font color="#c41230">semi-join</font>又有好多种执行策略,当执行策略为<font color="#c41230">DuplicateWeedout</font>时,也就是通过建立临时表来实现为外层查询中的记录进行去重操作时,<font color="#c41230">驱动表查询执行计划的Extra列将显示Start temporary</font>提示,<font color="#c41230">被驱动表查询执行计划的Extra列将显示End temporary</font>提示
LooseScan
在将In子查询转为<font color="#c41230">semi-join</font>时,如果采用的是<font color="#c41230">LooseScan</font>执行策略,则在驱动表执行计划的Extra列就是显示LooseScan提示
FirstMatch(tbl_name)
在将In子查询转为<font color="#c41230">semi-join</font>时,如果采用的是<font color="#c41230">FirstMatch</font>执行策略,则在被驱动表执行计划的Extra列就是显示FirstMatch(tbl_name)提示
Json格式的执行计划
作用
查看某个执行计划花费的成本
用法
在EXPLAIN单词和真正的查询语句中间加上FORMAT=JSON。
EXPLAIN FORMAT=JSON SELECT * FROM s1 INNER JOIN s2 ON s1.key1 = s2.key2 WHERE s1.common_field = 'a'
举一个栗子
Extented EXPLAIN
作用
比如可以看到 类似于查询优化器将我们的查询语句重写后的语句
使用
在执行计划执行后, 执行SHOW WARNINGS
0 条评论
下一页