[MySQL]查询的性能优化分析(二):Explain

MySQL Query Optimizer

MySQL Query Optimizer是MySQL中专门负责优化SELECT语句的模块,其主要功能是:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供MySQL认为最优的执行计划1

优化器执行过程:

  1. 客户端向MySQL发起Query请求;
  2. 命令解析器模块完成请求分类,区别出SELECT并转发给MySQL Query Optimizer(查询优化器);
  3. 查询优化器对整条Query进行优化,处理掉一些常量表达式的预算,直接换算成常量值;
  4. 查询优化器对Query中的查询条件进行简化和转换,如去掉一些无用或显而易见的条件、结构调整等;
  5. 分析Query中是否有Hint消息,是否可以通过Hint信息完全确定该Query的执行计划;
  6. 若没有Hint信息或不足以完全确定执行计划,则会读取所涉及对象的统计信息,根据Query进行写相应的计算分析,得出最后的执行计划。

查看执行计划:Explain

Explain的作用

使用EXPLAIN关键字可以通过模拟优化器执行SQL查询语句了解MySQL是如何处理SQL语句,从而分析查询语句或是表结构中的性能瓶颈。
使用Explain可以了解到:

  • 表的读取顺序:通过执行计划中的id判断
  • 数据读取操作的操作类型:通过执行计划中的select_type判断
  • 哪些索引可以使用:通过执行计划中的possible_keys判断
  • 哪些索引被实际使用:通过执行计划中的key判断
  • 表之间的引用:通过执行计划中的ref判断
  • 每张表有多少行被优化器查询:通过执行计划中的rows判断

Explain的使用

基本语法:Explain + SQL语句2
执行计划结果

图1 执行计划结果

执行计划包含的信息:

  • id:select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
    • id相同:执行顺序由上而下
      id相同,从上至下依次执行
    • id不同:如果是子查询,id的序号会递增,id值越大,优先级越高,越先被执行
      id不同,按id值从大到小依次执行
    • id相同、不同同时存在:相同的id视为一组,组内从上往下顺序执行,在所有id组中,id值越大,优先级越高,越先被执行
      id值相同、不同同时存在,按id值分组执行
  • select_type:操作类型
    • SIMPLE:不包含子查询或者UNION的简单查询
    • PRIMARY:包含任何子查询的查询中最外层查询(即最后加载的查询)
    • SUBQUERY:在SELECT子句或者WHERE子句中的子查询
    • DERIVED3:FROM子句中的子查询(若包含UNION,则外层查询将被标记为DERIVED)
      DERIVED
    • UNION:UNION后的查询
    • UNION RESULT:UNION连接的查询合并后的结果集
      UNION和UNION RESULT
  • table:数据查询基于的数据表
  • patitions:分区表命中的分区情况,非分区表该字段为Null
  • type:访问类型,常见的类型从好到坏的顺序是system>const>eq_ref>ref>range>index>ALL,一般来说,保证查询至少能够达到range级别,最好能达到ref级别
    • ALL:全表扫描,百万级别以上数据量的需要优化;
    • index:全索引扫描,扫描只会遍历索引树,相较于ALL从硬盘中读取全表数据,index扫描是从索引中读取全表数据,由于索引文件通常比数据文件小,使得index扫描比ALL扫描快;
      index
    • range:索引范围扫描,返回索引在给定范围的匹配行;
      range
    • ref:非唯一性索引扫描,多表联结查询匹配某个单独值的结果可能为多个匹配行;
    • eq_ref:唯一性索引扫描,多表联结查询匹配某个单独值的结果只有一个匹配行4,通常是将主键或唯一索引与联结的前表中的列进行比较;
      eq_ref
    • const:唯一性索引扫描,单表查询结果最多只有一个匹配行,通常是将primary key或unique索引的所有部分与常量值进行比较;
      const
    • system:表只有一行记录(等于系统表),这是const类型的特里,可以忽略不考虑。
  • possible_keys:显示可能应用在表查询中的所有索引,即查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被实际使用
  • key:实际使用的索引,如果为NULL,则没有创建索引,或者创建了索引但未使用
  • key_len:表示索引中使用的字节数,可以通过该列计算查询中使用的索引的长度,即索引字段的最大可能长度,并非实际使用长度。在不损失精确性的情况下,长度越短越好。
  • ref:表示被用于与索引比较的常量或列
  • rows:表示根据表统计信息及索引选用情况,大致估算出检索所需要读取的行数,行数越少越好
  • filtered:存储引擎返回的数据在server层过滤后,剩下满足查询的记录数量的比例(%)
  • extra:表示包含不适合在其他列中显示但十分重要的信息
    • using filesort:表示查询和排序的字段与索引不符(引用的字段个数和顺序不符),MySQL无法利用索引完成排序操作,会影响查询的性能,尽量优化消除。如下图,索引为empno,而排序字段为sal,此时索引的排序功能不再起作用;
      using filesort
    • Using temporary:表示MySQL在对查询结果排序时使用保存了中间结果的临时表,常见于order by和group by,会严重影响查询的性能;
    • Using Index:表示相应的查询操作中使用了覆盖索引5,避免访问了表的数据行
      • 存在using where:表明索引被用来执行索引键值的查找
        Using index和Using where
      • 不存在using where:表明索引用来读取数据而非执行查找动作
        Using index
    • Using where:表示使用了where过滤
    • Using index condition:表示相应的查询操作中同时使用创建了索引的列和未创建索引的列,5.6版本后加入的新特性
      • 存在Using where:表示未创建索引的列出现在WHERE子句中(emp表中对deptno、comm、sal三列创建了复合索引)
        Using index condition和Using where
      • 不存在Using where:表示未创建索引的列出现在SELECT子句中(emp表中对deptno、comm、sal三列创建了复合索引)
        Using index condition
    • Using join buffer:表示使用了联结缓存,join联结使用的比较多,建议增大缓存
    • Impossible where:WHERE子句的值总是false,不能获取到任何数据结果

  1. MySQL认为最优的数据检索方式,不意味着就是DBA认为的最优的数据检索方式,这部分认知的差异往往容易耗费时间。 ↩︎

  2. 本文中使用的数据表是Oracle自带的scott用户的数据表的MySQL副本,所以不另外提供建表语句 ↩︎

  3. MySQL会递归执行这部分查询,并把结果放在临时表里,即使这样会增加服务器负担。 ↩︎

  4. 官网原文:One row is read from this table for each combination of rows from the previous tables. ↩︎

  5. 覆盖索引(Covering Index):查询的数据列只需要从索引中就可以获取,不需要读取数据行,即一个索引包含了满足查询结果的数据列 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值