乐趣区

关于mysql:深入浅出-MySQL-执行计划

咱们所有的查问语句,MySQL 都会为其抉择一个最合适的执行打算。这个执行打算就展现了接下来执行查问的具体形式。在日常工作中咱们能够在 SQL 语句后面加上 EXPLAIN 关键字来查看具体的执行打算。

举个例子:

这种就是咱们日常用到 EXPLAIN 看到的最间接后果,也是这个查问语句最终的执行打算。

执行打算输入中各列详解

这个笔记就是用来解释这个执行打算中的各个列别离对应的是什么意思。不过在整顿具体之前,先简明扼要的说一下每个字段的具体含意:

列名 形容 备注
id 在一个大的查问中,每个 SELECT 对应一个惟一的 id id 小的先执行
select\_type SELECT 关键字对应的查问类型 连贯查问和子查问的时候才有用
partitions 匹配的分区信息
type 针对单表的拜访形式 咱们最罕用的字段
possible\_Keys 可能用到的索引
key 理论应用的索引
key\_len 理论应用的索引长度
ref 当应用索引列等值查问时,与索引列等值匹配的对象信息
rows 预估的须要读取的记录条数
filtered 针对预估的须要读取的记录,通过搜寻条件过滤后残余记录条数的百分比 rows 和 filtered 在判断连贯查问的扇出的时候,是一个十分重要的判断指标。
Extra 一些额定的信息 重点

id 列

通常来说一个查问语句都有一个或多个 SELECT,在执行打算中每一个 SELECT 都会被独自调配一个 id。为不便了解,咱们举几个简略的例子:

这种单表等值查问,不言而喻的只有一个 SELECT 而且实际上也只拜访了一张表,所以上面的 id 只有一个是 1。这种状况下其实咱们是无奈判断这个 id 到底是因为 SELECT 关键字独自调配的,还是依据表独自调配的。所以这里,咱们须要再来看一个连贯的查问的状况。这里其实无论是内查问还是外查问都是一样的,我在这里举了一个外查问的例子。

从后果上咱们能够看到,这里有两个表别离是 s1 和 s2,然而他们还是只调配了同样的 id,这样就能够证实 id 列的值是依据 SELECT 调配的了吗?本着不试不爽的态度,咱们再来看一个 UNION 子句的状况。

从下面这三个例子中,咱们就能够证实执行打算中每一个 SELECT 都会被独自调配一个 id。置信在看 UNION 这个例子的执行打算中,你或者感到一点奇怪。为什么我这是两个表的查问后果的 UNION,怎么在执行打算中呈现了第三行,而且这一行还这么奇怪,id 是 NULL

这个其实是一个外部的长期表,MySQL 为了让 id 为 1 和 2 的数据进行去重,他应用的是外部长期表,MySQL 在外部创立了一个名为 <union1,2> 的长期表。id 为 null 是示意这个表是长期的。

select_type 列

在后面的例子中咱们也说到了一个查问语句中可能蕴含若干个 SELECT,查问若干个表。每一个表都是一个小查问,而 select_type 就是来阐明这个小查问的类型的。

这一部分的笔记,我后期曾经整顿过了。如果大家感兴趣能够间接点击上面的连贯去查看,我这里就不再赘述了。

具体解释 MySQL explain 中的 select_type 是什么

table 列

无论咱们的查问语句有多简单,其中蕴含多少个表,应用什么连贯、子查问、UNION 子句等形式进行组合,到最初还是对每个表进行单表拜访。

EXPLAIN 语句的输入的每条记录都对应着某个单表的拜访办法,该记录的 table 列代表该表的表名。当然这些表不是必须得是数据库中理论存储的表,也有可能是为了不便去重等起因 MySQL 本人搞的长期表,比如说之前 UNION 的状况。

type 列

坦率的说,这一列应该是咱们在查看 MySQL 的执行打算的时候最常看也是最无脑看的一列了。因为咱们在学习阿里巴巴的《Java 开发标准》的时候,下面明确规定了 SQL 的级别,原文如下:

开发标准中的这个所谓的级别,实质上就是说的 EXPLAIN 执行打算中 type 列的级别。残缺的拜访办法包含 system、const、eq_ref、ref、fulltext、ref_or_null、index_merge、unique_subquery、index_subquery、range、index、ALL。为了不便大家浏览,我先独自整顿一个表格来阐明各个级别的具体含意,而后再别离具体阐明级别信息。

类型 形容 备注
system 如果表外面只有一条数据,而且表应用的存储引擎(如 MyISAM)的统计信息是精确的。 条件太刻薄,简直见不到
const 应用主键或惟一二级索引与常数进行等值匹配时 效率高,常见
eq_ref 连贯查问是,如果被驱动表是通过主键或者不容许为 null 的惟一二级索引列进行等值匹配的办法拜访的 常见
ref 通过一般的二级索引与常数进行等值匹配时 常见
fulltext 全文索引 简直用不到
ref_or_null 对二级索引进行等值匹配且该索引的值也能够为 null 的时候 常见
index_merge 两个以上的索引合并 不常见
unique_subquery 如果子查问能够转换为 EXISTS 子查问,而且转换之后能够应用主键或者不容许为 null 的惟一二级索引进行等值匹配
index_subquery 如果子查问能够转换为 EXISTS 子查问,而且转换之后能够应用一般二级索引进行等值匹配
range 应用索引进行范畴查问 常见
index 应用索引笼罩,扫描前部索引记录的时候 常见,然而不举荐
ALL 全表扫描 常见,然而不举荐

事实上,如果只是不便理解这一列的几种级别的话,我感觉下面这个表格就够用了,然而如果你心愿针对每每一种级别都想要有更加深刻的理解,能够点击查看我之前公布的文章:

具体解释 Type 列

possible_keys 列 和 key 列

在 EXPLAIN 输入的执行打算中,possible_keys 列示意在某个查问语句中,对某表执行单标查问时可能用到的索引有哪些,而 key 则是则是示意,最终用到的索引是什么。举个例子:

然而须要留神的是,并不是能够供选的索引越多越好,因为能够供选择的索引越多,查问优化器在计算查问老本的时候破费的工夫就越长。

MySQL 的查问优化器的抉择机制因为牵扯到成本计算,如果要阐明的话占用的篇幅会十分长,我这里就临时不开展形容了。我前面会独自整顿一篇文章来阐明 MySQL 的成本计算逻辑,敬请期待。

ref 列

当咱们的查询方法的类别是 const、eq_ref、ref、ref_or_null、unique_subquery、index_subquery 中的其中一个时,ref 列展现的就是与索引列进行等值查问的货色是啥。

它有时是一个常数,有时是一个列,甚至能够是一个 function。这个其实没啥技术含量,我猜想大家看图就能搞明确,所以这里就不赘述了。

rows 列

如果查问优化器决定应用全表扫描的形式对某个表执行查问时,执行打算的 rows 列就代表预计须要扫描的行数,如果应用索引来执行查问时,执行打算的 rows 列就代表预计扫描的索引记录行数。

filtered 列

filtered 列示意针对预估的须要读取的记录,通过搜寻条件过滤后残余记录条数的百分比。这个感觉说起来不好了解,咱们能够举两个例子:

在这个表中,咱们进行全表扫描,显示咱们要扫描 57736 行数据。然而通过我加上 where 条件之后,当初预计须要扫描的行数就是 57736 x 10% = 5773 行了。

Extra

Extra 是用来阐明一些额定的信息的,其实依据下面的内容,咱们大略晓得了一个 SQL 的执行打算输入列都是什么,别离代表什么意思。然而通过这列中的阐明信息,咱们能够更精确的了解 MySQL 到底如何执行给定的查问语句。

Extra 列中能够给出的申明信息十分十分的多,然而我在这里还是做了一些精简,因为这外面实际上有很多咱们日常工作中基本用不上(或者很少见到)。咱们只有对上面的这些形容有印象就能够了,如果遇到生疏的,能够面向 Google 编程。

  • No tables used: 查问语句中没有 FROM 子句
  • Impossible WHERE 查问语句的 WHERE 子句条件永远为 false。如: WHERE 1 != 1
  • No matching min/max row:查问列表处有 MIN 或者 MAX 汇集函数,然而没有记录合乎 WHERE 子句中的搜寻条件
  • Using index : 应用了笼罩索引。
  • Using index condition : 搜寻条件中尽管呈现了索引类,然而却不能充当边界条件来造成扫描区间。比方 key1 > ‘z’ and key1 like ‘%a’
  • Using where: 当某个搜寻条件须要在 server 层进行判断时,提醒 Using where
  • Using join buffer:连贯查问的执行过程中,当被驱动表不能无效的利用索引放慢访问速度的时候,应用 join buffer 缓冲区来放慢查问速度的时候,会提醒这个。
  • Using filesort:在有些状况下对后果集中的记录进行排序的时候,是能够应用到索引的。
  • Using temporary: 在许多查问的执行过程中,借助长期表进行去重、排序等。
退出移动版