MySQL数据库系列(四):MySQL数据库的执行计划怎么看


数据库执行计划是优化SQL时必备的技能,如果只靠猜和借鉴前人的经验,只会让自己不断的踩坑。

1. 索引了解一下

在写执行计划之前需要先了解一下数据库有哪些索引。

  • 普通索引:建立在普通的单列上,单纯的索引列,没有唯一性的要求。
  • 组合索引:在表中的多个字段组合创建的索引。
  • 唯一索引:当前索引列的值是唯一的,不可重复的。
  • 全文索引:全文索引如同普通索引的细化,只能在char、varchar、text数值类型类中建立。

其中组合索引有一个特性就是最左前缀原则,组合索引的最左列被使用到才会让整个组合索引生效。比如一个索引idx_name_phone,在索引列中name在前面,phone在后,当单纯是使用phone来查询的时候,是不会走idx_name_phone索引的,只有在name被使用的时候,才会让整个索引起作用。

全文索引只能在MyISAM存储引擎里使用,其他引擎不支持,他的特点如下:

  • 默认只支持英文,不支持中文,需要借助第三方工具sphinx和coreseek来实现
  • 只在MyISAM存储引擎中适用,其他存储引擎不支持
  • 语法不同其他索引,需要使用指定的match against语法,如下示例:
//其中title和content是建立了全文索引的列
select * from atricle where match (title,content) against ("mysql");

另外还有两种索引的存储结构,分别是聚集索引和非聚集索引。

  • 非聚集索引,索引文件和数据存储文件是分别的两个文件。此索引又被成为非聚簇索引
  • 聚集索引,索引文件和数据存储在同一个文件中,此索引又被称为聚簇索引

这两种索引其实准确的说是两种索引存储结构,和上面的几种索引是有本质上的区别。这两种索引在理解MySQL的MyISAM存储引擎和InnoDB存储引擎在B+Tree的时候需要,以后的文章会有体现,这里就不多写了,作为一个了解。

最后需要了解一个索引上常说的一个概念,叫做覆盖索引,听起来又是一种索引,但实际上不是,从语法上可以理解为索引的覆盖。表示在条件中使用到索引列,并且同时索引列也在需要查询的列中,此时就会使用到覆盖索引。但是需要注意的是只有BTree会存储索引列,其他的如哈希索引、空间索引等都不存储。因此可以理解为MySQL中只能对使用BTree数据结构的存储引擎适用。

在SQL优化的时候会经常用到覆盖索引,可以解决大部分索引失效的情况,以后在写SQL优化的时候再具体说。

2. 执行计划

2.1 概念

想要看执行计划,只需要在SQL语句的前面加上explain关键字即可。执行结果有可能是多行,但是列基本是固定的。

所拥有的基本列如下:

2.2 id

包含一组数字,表示查询中执行select子句或操作表的顺序。

这里会出现三种情况:

  • 多行执行计划的id相同,这个时候表示自上而下依次执行
  • 多行执行计划的id都不相同,id的值越大表示优先级越高,越早被执行
  • 多行执行计划的id有相同有不同,此时就按照id来分组,同一组按照自上而下依次执行,不同组根据id的值来决定执行顺序,id越大优先级越高,越早被执行

2.3 select_type

表示多个select字句的类型,主要的类型有下面几种:

  • simple:查询语句中不包含子查询或者union查询
  • primary:查询中若包含任何复杂的子部分,最外层查询则被标记为:primary
  • subQuery:select或where列表中包含了子查询,该子查询被标记为:subQuery
  • derived:在from列表中包含的子查询被标记为:derived,表示衍生的意思
  • 若第二个select出现在union之后,则被标记为union;若union包含在from子句的子查询中,外层select将被标记为:derived
  • 从union表获取结果的select被标记为:union result

2.4 type

表示MySQL在表中找到所需行的方式,又称“访问类型”。常见的类型有:ALL、index、range、ref、eq_ref、const、system。从左到右,由最差到最好。

  • ALL:full table scan,全表扫描

  • index:index表示使用了索引,但缺点是扫描的是全表索引

  • range:索引范围扫描,对索引的扫描开始于某一点、结束于某一点,返回匹配值域的行,常见于between、in、<、>等的查询

  • ref:非唯一性索引扫描,返回匹配某个单独值的所有行。

  • eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描

  • const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键或者唯一索引置于where列表中,MySQL就能将该查询转换为一个常量

2.5 possible_keys

指出MySQL可能使用到的索引,但是实际上有没有使用时不确定的。另外如果此列的值为null,也有可能走了索引。因此这个列只作为一个参考值,主要是看下面的key列。

2.6 key

显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。

2.7 key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。

当是联合索引的时候,如果多列中只有其中几列使用到,对应key_len长度就是这几列的总长度之和。可以用来判断哪些条件用到索引,哪些条件没有用到索引,或者索引是否失效。

这里需要了解的是各种类型长度的计算,因为这个长度并不是在创建表时指定的长度(L)。

  • 当是char的时候,长度是Lx3,另外如果该列可以为空,需要在计算的结果上加一
  • 当是varchar的时候,长度是Lx3+2,另外如果该列可以为空,需要在计算的结果上加一
  • 当是int类型的时候,固定长度为4,如果可以为空,就加一
  • 当是datetime类型的时候,在MySQL5.6版本之前是固定长度4,之后的版本固定长度为8,如果可以为空,加一即可
  • 当是timestamp类型的时候,固定长度为4,如果可以为空,就加一

图中的user_name(长度32)和user_phone(长度11)是建立的联合索引,通过key_len可以看的出来,当只使用user_name查询的时候,索引长度是98,当两个都作为查询条件的时候,索引长度为133。

2.8 ref

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值。

在第二行中,ref就明确的指出使用了具体那一列。

2.9 rows

表示MySQL根据表统计信息及索引选用情况,估算找到所需的记录所需要读取(扫描)的行数。这个很好理解。

2.10 extra

包含不适合在其他列中显示但十分重要的额外信息

  • Using index:该值表示相应的select操作中使用了覆盖索引,如果没有使用覆盖索引对应的值是Using index condition。

注意:如果要使用覆盖索引,一定要注意select列表中只取出需要的列,不可select *,因为如果将所有字段一起做索引会导致索引文件过大,查询性能下降。

  • Using where:表示MySQL服务器在存储引擎收到记录后进行“后过滤”(Post-filter),如果查询未能使用索引,Using where的作用只是提醒我们MySQL将用where子句来过滤结果集。

  • Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询

  • Using filesort:MySQL中无法利用索引完成的排序操作称为“文件排序”(分组也是一样)

上面的Using temporary图中就涉及到Using filesort,因为user_name和user_phone是联合索引,只使用user_phone不符合最左前缀原则,因此不能实现按索引分组,使用了文件分组。在后期的实验中,发现普通索引也是不能实现按索引分组或者排序。

3. MySQL执行计划的局限

  • EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
  • EXPLAIN不考虑各种Cache
  • EXPLAIN不能显示MySQL在执行查询时所作的优化工作
  • 部分统计信息是估算的,并非精确值
  • EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划

4. 参考文章

Explain语法


文章作者: 程序猿洞晓
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 程序猿洞晓 !
评论
 上一篇
MySQL数据库系列(五):MySQL之SQL优化十大口诀了解一下 MySQL数据库系列(五):MySQL之SQL优化十大口诀了解一下
SQL优化,心中永远的痛,同事写的各种复杂SQL,各种坑,有时候想拿出来优化一下,但是总感觉力不从心,不知从哪里下手。……。全值匹配是最优,最左前缀原则要注意,乱在索引列上操作惹祸害,范围查询记得放后面,不等于使用要小心,空和非空要注意,模糊查询通配符勿乱放,字符串查询加引号,OR变UNION效率会更高,记得覆盖索引尽量用。
2018-10-11
下一篇 
MySQL数据库系列(三):MySQL数据库的ACID事务特性和隔离性级别 MySQL数据库系列(三):MySQL数据库的ACID事务特性和隔离性级别
事务的特性主要有四种,简称为ACID。分别如下:原子性(atomicity):一个事务内是一个最小的操作单元,在此单元里操作成功或者失败都是相同的,不会存在部分成功部分失败的问题。隔离性(isolation):多个事务之间是隔离开的,事务之间对数据的操作是不会互相影响的。但是对于数据库来说有不同的隔离级别,事务之间的影响也是不同的。
2018-10-06
  目录