MySQL EXPLAIN执行计划详解

MySQL EXPLAIN执行计划详解详细介绍了MySQLEXPLAIN执行计划的各个字段的含义以及使用方式。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

详细介绍了MySQL EXPLAIN执行计划的各个字段的含义以及使用方式。

调用EXPLAIN可以获取关于查询执行计划的信息,以及如何解释输出。EXPLAIN命令是查看查询优化器如何决定执行查询的主要方法,但该动能也有局限性,它的选择并不总是最优的,展示的也并不一定是真相。

1 调用EXPLAIN

要使用EXPLAIN,只需要在SELECT 关键字之前增加 EXPLAIN这个词。MySQL会在查询上设置一个标记。当执行查询时,这个标记会使其返回关于在执行计划中每一步的信息,而不是真正完全的执行该语句。

它会返回一行或多行信息,显示出执行计划中的每一部分和执行的次序。在查询中,每个表的输出只有一行,若多表关联,则输出多行。别名表单算为一个表,因此如果把表和自己连接,输出中也会有两行。这里的表的定义非常的广:可以是一个子查询,一个 UNION 结果。

EXPLAIN有两个变种:

  1. EXPLAIN EXTENDED:看起来和正常的EXPLAIN行为一样,但他会告诉服务器“逆向编译”执行计划为一个 SELECT 语句(SHOW WARNINGS 后能看到),该命令在MySQL5.0之后可用,MySQL5.1开始还额外增加一个 filtered 列。
  2. EXPLAIN PARTITIONS:如果查询基于分区表的话,将显示查询将访问的分区。MySQL5.1以及更新的版本支持。

增加了EXPLAIN之后,MySQL可能仍然会执行部分查询,如果查询中FROM字句中包括子查询,那么MySQL实际会执行子查询的,并将其结果放在一个临时表中,然后完成外层查询优化。

EXPLAIN 返回的只是个近似结果,并且还有相关是的限制:

  1. 不会告诉你知道触发器、存储过程或 UDF 如何影响查询。
  2. 不支持存储过程,尽管可以单独抽取查询进行 EXPLAIN。
  3. 不会告诉你查询执行中所做的特定优化。
  4. 不会显示关于查询的执行计划的所有信息。
  5. 无法区分具有相同名字的事物,例如,它对内存排序和临时文件排序都使用“filesort”,并且对磁盘上和内存中的临时表都显示“Using temporary”。
  6. 可能会误导,例如:可能会对一个很小的limit查询显示全索引扫描。
  7. 只能解释select查询(5.6以后允许解释非select语句),不会对存储过程调用和INSERT、DELETE、UPDATE或其他语句做解释,但可通过重写某些非 SELECT 查询以利用 EXPLAIN。

2 EXPLAIN中的列

2.1 id

一个编号,表示select所属的行。如果查询中没有子查询或关联查询,那么只会有唯一的SELECT,每一行的该列中都将显示一个1,否则,内层的SELECT语句一般会顺序编号,对应于其在原始语句中的位置。id越大执行优先级越高,id相同则认为是一组,从上往下执行,id为NULL最后执行。

例如UNION查询中最后对于临时表的查询,它的id就为null,因为临时表并不在原sql中出现。

EXPLAIN select * from contacts where contact_id <1000
UNION 
select * from contacts where contact_id >99000

在这里插入图片描述

2.2 select_type

表示对应行是简单还是复杂的查询。

  1. SIMPLE,简单SELECT,查询不包括UNION和子查询。
  2. PRIMARY,查询中若查询包含任何复杂的子部分,最外层的select被标记为PRIMARY。其他部分标记如下:
    1. SUBQUERY,包含在SELECT子句(不在from子句中)中的子查询的SELECT,结果不依赖于外部查询。
    2. DERIVED,包含在from子句中的子查询中的SELECT。MySQL会递归执行并将结果存放在一个临时表中,也称为派生表,因为该临时表是从子查询中派生来的。
    3. UNION,UNION中的第二个或后面的SELECT。第一个SELECT被标记就好像它以部分外查询来执行,因此第一个SELECT可能显示为PRIMARY。如果UNION被FROM字句中的子查询包含,那么它的第一个SELECT被标记为DERIVED。
    4. UNION RESULT,用来从UNION的匿名临时表中检索结果的SELECT。

除了上面这些,SUBQUERY和UNION还可以被标记为DEPENDENT和UNCACHEABLE,DEPENDENT意味着SELECT 依赖与外层查询中发现的数据;UNCACHEABLE意味着SELECT 中的某些特性阻止结果被缓存于一个 Item_cache 中。

EXPLAIN select * from contacts where contact_id =99000

在这里插入图片描述

2.3 table

显示了EXPLAIN对应行正在访问哪个表。通常情况下,它相当表明了:那就是那个表,或者该表的别名。

可以通过该列从上到下观察MySQL的关联优化器为查询选择的关联顺序。

from字句中有子查询的时候,table列是<derivedN>的形式,N指向子查询id,这里N总是指向EXPLAIN输出结果中的后面的一行。

当有UNION时,UNION RESULT的table列包含一个参与UNION的id列表,UNION RESULT总是出现在UNION中所有参与行之后,例如<union 1,2>

2.4 type

关联类型,或者说访问类型,该字段表明MySQL决定如何查找表中的行。

常用的访问类型如下(性能依次从最差到最优):

  1. ALL全表扫描,从头到尾的查找所需要的行。但仍然存在例外,例如使用了 LIMIT ,或者Extra 列中显示 “Using distinct/not exists”。
  2. index跟全表扫描一样,只是MySQL扫描表时按照索引次序进行而不是行,主要优点是避免了排序;缺点是要承担按索引次序读取整个表的开销。这通常意味着如实按照随机次序访问行,开销较大。如果Extra 列中显示 “using index”,说明MySQL正在使用覆盖索引,这样就不需要按索引次序访问每一行数据,开小会少很多。
  3. range范围扫描,就是一个有限制的索引扫描,使用一个索引来检索给定范围的行,不需要遍历全部索引。范围扫描通常出现在between,>,<,>=等操作中。in()和OR也会显示范围扫描,但这两者其实是不同的访问类型,性能上也有差异。此类查找的开销根ref索引访问的开销相当。
  4. ref索引访问,也叫索引查找。返回所有匹配某个单个值的行,然而它可能会找到符合条件的多个行。此类索引访问只有当使用非唯一性索引或者唯一索引的非唯一性前缀时才会发生。把他叫ref是因为他要和某个参考值相比较。这个参考值或者是一个常数,或者来自多表查询前一个表里的结果值。
  5. eq_ref:使用这种索引查找,MySQL清楚的知道最多只返回一条符合条件的记录,使用主键或者唯一值索引查找时能看到这种方法。MySQL对于这种访问类型的优化做得非常好,因为它知道到无需估计匹配行的范文或者在找到匹配行后再继续查找(因为值不会重复)。
  6. const,system当MySQL能对查询的某部分进行优化并将其转换成一个常量时,它就会使用这些访问类型。比如通过将某一行的主键访问WHERE字句的方式来查询主键:SELECT id from t where id = 1。此时MySQL就能把这个查询转换为一个常量。
  7. NULL这种访问方式意味着MySQ能在优化阶段分解查询语句,在执行阶段甚至不需要再访问表或者索引。例如,从一个索引列里选取最小值可以通过单独查询索引来完成,不需要在执行时访问表。
  8. index_merge索引合并(index merge)。MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,引入了索引合并优化技术,对同一个表可以使用多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)。index merge使得我们可以使用到多个索引同时进行扫描,然后将结果进行合并。听起来好像是很好的功能,但是如果出现了 index intersect merge,那么一般同时也意味着我们的索引建立得不太合理,因为 index intersect merge 是可以通过建立复合索引进行更一步优化的。

2.5 possible_keys

显示查询可以使用哪些索引,这是基于查询访问的列和使用的比较操作符来判断的。该列表是在优化过程的早期创建的,因此列出来的索引对于后续实际优化过程可能是没有用的。

2.6 key

显示mysql决定采用哪一个索引来优化对该表的访问,如果该索引没有出现在possible_keys列中,那么MySQL选用它是出于另外的原因——例如,它可能选择了一个覆盖索引,哪怕它没有WHERE字句。

possible_keys表示哪些索引有助于高效查找,而key表示该索引可以最小化查询成本。

如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX

2.7 key_len

MySQL在索引中使用的字节数,通过这个值可以算出具体使用了索引中的哪些列,计算时需要考虑字符集,如果字段允许为 NULL,需要1字节记录是否为 NULL。

key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

2.8 ref

这一列显示了在key列记录的索引中,表查找值所用到的列或常量,即哪些列或常量被用于查找索引列上的值。常见的有:const(常量),func,NULL,字段名(例:film.id)

2.9 rows

这一列是mysql估计要读取并检测的行数,注意这个不是结果集里的行数,而是MySQL为了找到符合查询的每一个标准的那些行而必须读取的行的平均数。

有时候该估值可能很不精确,该数字也反映不了LIMIT字句的真正检查行数。

2.10 Extra

这一列展示的是额外信息。常见的重要值如下:

  1. Using index:表示MySQL将使用覆盖索引,这发生在对表的请求列都是同一索引的部分的时候,返回的列数据只使用了索引中的信息,而没有再去访问表中的行记录。是性能高的表现。
  2. Using index condition:在5.6版本后加入的新特性索引下推(Index Condition Pushdown,ICP),在索引遍历过程中,对索引中包含的字段先做判断(即使该字段没有使用到索引),直接过滤掉不满足条件的记录,减少回表次数。
  3. Using where:意味着MySQL服务器将在存储引擎检索行后再进行过滤。就是先通过索引读取整行数据,再按 WHRER条件进行检查,符合就留下,不符合就丢弃。查询的列未被索引覆盖。
  4. Using temporary:MySQL需要创建一张临时表来中间结果并进一步处理,比如union、group by、distinct等,出现这种情况一般是要进行优化的,首先是想到用索引来优化。
  5. Using filesort:MySQL会对结果使用一个外部索引排序,而不是按索引次序从表里读取行,即filesort(文件排序)。此时mysql会根据联接类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息。这种情况下一般也是要考虑使用索引来优化的。filesort有两种,一种是内存排序,一种是磁盘排序,无法得知。
  6. Distinct: 一旦MySQL找到了与行相联合匹配的行,就不再搜索了,常见于关联查询。
  7. No tables used:Query语句中使用from dual 或不含任何from子句。
  8. Using join buffer:使用了连接缓存,join语句用到了缓冲区。

参考资料:

  1. 《 MySQL 技术内幕: InnoDB 存储引擎》
  2. 《高性能 MySQL》
  3. 《MySQL实战45讲 | 极客时间 | 丁奇》

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/180969.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • nginx和apache的区别[通俗易懂]

    nginx和apache的区别[通俗易懂]简单的说apachehttpd和nginx都是web服务器,但两者适应的场景不同,也就是两者专注于解决不同的问题。apachehttpd:稳定、对动态请求处理强,但同时高并发时性能较弱,耗费资源多。nginx:高并发处理能力强、擅长处理静态请求、反向代理、均衡负载。在这篇文章详细列出了apache与nginx的13个异同点,下面我们来一一分析其原理。1、nginx相对于apache的优点:轻量级,同样起web服务,比apache占用更少的内存及资源,抗并发,nginx处理请求是异

  • 在线学习Java的资源网站

    CodeGym(https://codegym.cc/):一个在线Java编程课程,80%的内容是练习,适合一窍不通的入门者。 CodeAcademy(https://www.codecademy.com/):该课程注重的是在找工作时非常有用的技术能力。 除此之外还有在线视频课程,如Coursera(https://www.coursera.org/)或Udemy(ht…

  • 二传感器尺寸「建议收藏」

    二传感器尺寸「建议收藏」说到传感器的尺寸,其实是说感光器件的面积大小,这里就包括了CCD和CMOS。感光器件的面积越大,CCD/CMOS面积越大,捕捉的光子越多,感光性能越好,信噪比越高。下面是家用小DC图像传感器尺寸换算为公制的大小(单位为毫米):2/3英寸的画幅面积为(8.8×6.6mm)1/1.8英寸的画幅面积为(7.178×5.319mm)1/2英寸的画幅面积为(6.4×4.8mm)1/2.7英寸的画幅面…

  • 项目管理-5大过程组-10大知识领域-47过程

    项目管理五大过程组:1、启动过程组:获得授权,定义一个新项目或现有项目的一个新阶段,正式开始该项目或阶段的一组过程。2、规划过程组:明确项目范围,优化目标,为实现目标而制定行动方案的一组过程。3、执行过程组:完成项目管理计划中确定的工作以实现项目目标的一组过程。4、监控过程组:跟踪、审查和调整项目进展与绩效,识别必要的计划变更并启动相应变更的一组过程。5、收尾过程组:为完结所有过程组的…

  • exit与return的区别

    exit与return的区别

  • 客观赋权法——变异系数法

    客观赋权法——变异系数法一、变异系数法的概念变异系数法是根据统计学方法计算得出系统各指标变化程度的方法,是一种客观赋权法。根据该方法变化差异较大的指标权重较大,变化差异较小的指标权重较小,从而根据指标的统计学规律确定其重要程度。变异系数法是一种较为客观的方法,能够客观的反应指标数据的变化信息,该方法能够比较客观的求出各指标的权重。根据各评价指标当前值与目标值的变异程度来对各指标进行赋权,当各指标现有值与目标值差距较大时,说明该指标较难实现目标值,应该赋予较大的权重,反之则应该赋予较小的权重。二、变异系数法的步骤(1)原

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号