阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MySQL中SQL执行计划详解

129次阅读
没有评论

共计 4408 个字符,预计需要花费 12 分钟才能阅读完成。

MySQL 执行计划是 sql 语句经过查询优化器后,查询优化器会根据用户的 sql 语句所包含的字段和内容数量等统计信息,选择出一个执行效率最优(MySQL 系统认为最优)的执行计划,然后根据执行计划,调用存储引擎提供的接口,获取数据。

但是,在 MySQL 执行的时候,到底使用了一个什么样的执行计划,有没有用到索引。当数据规模比较大的时候,sql 执行的时候,执行计划不同,会直接影响 sql 的执行速度。这个时候,就需要对 sql 语句执行进行调试。

MySQL 我们在调试 sql 语句的时候,不会像我们写 Java 或者其他语言代码那样通过打断点的方式进行代码调试。这个时候,我们就需要通过查看执行计划来调试我们的 sql 了。MySQL 通过 EXPLAIN 来查看执行计划,我们写 sql 语句的时候,在语句之前加一个 EXPLAIN 就可以了。EXPLAIN 可以用在 SELECT、DELETE、INSERT、PEPLACE 以及 UPDATE 等语句中,如:

EXPLAIN SELECT
    *
FROM
    school
WHERE
    school_nick = ‘ 县第一小学 ’

EXPLAIN SQL

执行后,结果如下:

MySQL 中 SQL 执行计划详解

这里介绍下每个字段以及每个字段的含义:

id

id 是执行计划的标识符,是 SELECT 查询的序号。如果结果集会跟其他表的结果用 UNION 关键字相结合,那么 id 可能为空。

id 是否为空,对执行计划的影响不大。

select_type

select_type 表示 sql 语句查询的类型。具体表示如下表:

select_type 的值          含义
SIMPLE 简单的 select 查询,没有使用关联和子查询。
PRIMARY 最外层 select,包含子查询的时候,最外层的查询
UNION 在一个 UNION 查询中,第二次或以后的子查询操作
DEPENDENT UNION 在一个 UNION 查询中,第二次子查询或以后的 SELECT 查询的时候需要依赖外部的查询                         
UNION RESULTUNION 的返回结果集
SUBQUERY 子查询语句的第一个 select 语句
DEPENDENT SUBQUERY                                  依赖外部查询的第一个子查询
DERIVED 派生表——该临时表是从子查询派生出来的,位于 form 中的子查询
MATERIALIZED 物化子查询(不确定啥意思,以后研究后再回来补充,或者大神指教)
UNCACHEABLE SUBQUERY      无法缓存结果的子查询,必须为外部查询的每一行重新计算
UNCACHEABLE UNIONUNION 中的第二个或以后的不可缓存的子查询。

table

输出行引用的表的名称。一般为表格名称或别名,也可能为如下值:

1.UNION 的并集结果集。

2.derivedN 当前行指向派生结果集。可能是一个派生表,例如来自 FROM 子句的结果集。

3.subqueryN 当前行指向一个子查询的结果集。

type

连接类型。该列输出表示如何连接表。下面的类型表示从最好的到最坏的类型

1.system 该表只有一行(= 系统表)。这是 const 连接类型的特例。

2.const 最多只有一行匹配,在查询开始的时候,计算出常量对应的地址,直接访问,例如:select * from test where  name =’zhang’ 当 name 是唯一索引的时候,就有可能出现 const。const 非常快,因为它只读一次。

3.eq_ref 除了 system 和 const 类型之外,这是最好的连接类型。当两个表联查时使用索引的所有部分(针对的是组合索引),且索引是 主键或唯一索引时使用它。使用“=”运算符来进行索引列的比较。

4.ref 非唯一索引扫描,返回某个匹配值的所有行。常用语非唯一索引。这里对于 eq_ref 和 ref 不熟悉的同学,可以看以下代码:

— 给 test 表的 name 字段加唯一索引,test2 的 job 行添加非唯一索引。
— 这个代码执行后,首先执行 test2 的查询,查出 job =‘teacher’的所有集合。
— 所以 test2 的 typ 是 ref 表示的是匹配 job =‘teacher’的一个结果集。
— 然后从结果集中取出 name 的集合,去匹配 test1.name 的结果。因为 test1.name 是唯一索引,所以一个 name 最多匹配到一条记录,所以 test 的 type 是 ref
EXPLAIN SELECT
    *
FROM
    test,
    test2
WHERE
    test. NAME = test2. NAME
AND test2.job = ’33’

test ref and eq_ref

执行结果如下图:

MySQL 中 SQL 执行计划详解

5.fulltext 使用 fulltext 索引进行查询。

6.ref_or_null 这种链接类型类似于 ref,但是,除了 ref 之外,还对包含 null 的值进行了搜索。常用于解析子查询。代码示例如下:

SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;

7.index_merge 这个链接类型表示使用索引合并优化。输出内容包含在索引列表中。

8.unique_subquery 索引查找,替换子查询,以提高效率。

value IN (SELECT primary_key FROM single_table WHERE some_expr)

9. index_subquery 类似于 unique_subquery 但是替换 in 子查询,适用于非唯一索引,代码:value IN (SELECT key_column FROM single_table WHERE some_expr)

10.range 扫描部分索引,对索引的扫描从某一点开始,返回的是某个索引区域的值。常见的有基于索引的 < ,> 等的查询。

11. index 扫描全部索引,对索引进行整体扫描。

12.all 全表扫描,最慢的查询。应该避免

  possible_keys

可能使用的 key,指出当前查询涉及到的行都含有那些索引。如果有索引就会列出,但是不一定会被使用。

key

实际使用的索引。如果没有使用索引,显示 null。

key_len

表中对应的索引最大可能长度。可以通过设置索引长度改变该值。例如:一个 varchar(255)的索引长度为 255,可是我们使用不到那么长,我们可以取字符串的前五位作为索引。这时 key_len 就是 5. 这里关于索引值的长度的选取规则,以后有机会再写一篇博客详细介绍。

ref

哪些字段和 key 一起被使用。没用过。

rows

受影响的行数。不是特别精确的。

Extra

解释额外的信息。包含 mysql 对于 query 优化的时候的一些附加信息。非常有用。可能出现的结果如下:

  • const row not found 该表为空
  • Deleting all rows  表格内数据被标记删除,正在删除中(某些存储引擎支持一种方法,以简单快捷的方式删除所有行,这时查询就会出现这个提示)
  • Distinct  MySQL 正在寻找不同的值,因此它在找到第一个匹配行后停止为当前行组合搜索更多行。
  • FirstMatch(tbl_name) 半连接 FirstMatch 连接快捷方式策略用于 tbl_name。
  • Full scan on NULL key 当优化程序无法使用索引查找访问方法时,子查询优化将作为回退策略发生。
  • Impossible HAVING 该 HAVING 子句始终为 false,无法选择任何行。
  • Impossible WHERE 该 WHERE 子句始终为 false,无法选择任何行。
  • Impossible WHERE noticed after reading const tables MySQL 已经读取了所有 const(和 system)表,并注意到该 WHERE 子句始终为 false。
  • No matching min/max row 没有行满足查询的条件的行
  • no matching row in const table  对于具有连接的查询,有一个空表或没有满足唯一索引条件的行的表。
  • No matching rows after partition pruning  对于 DELETE 或 UPDATE,优化器在分区修剪后发现没有删除或更新的内容。
  • No tables used 查询没有 FROM 子句
  • Not exists 查询的内容不存在
  • Plan isn’t ready yet 优化程序尚未完成为在命名连接中执行的语句创建执行计划时,会出现此值。
  • Range checked for each record MySQL 发现没有好的索引可以使用,但发现在前面的表的列值可能会使用某些索引。
  • Recursive  递归
  • Skip_open_table,Open_frm_only,Open_full_table
    • Skip_open_table:表文件不需要打开。该信息已从数据字典中获得。
    • Open_frm_only:只需要读取表信息的数据字典。
    • Open_full_table:未优化的信息查找。必须从数据字典中读取表信息并读取表文件。
  • unique row not found  对于查询,没有行满足 索引或表的条件。
  • Using filesort  使用文件排序。MySQL 必须执行额外的传递以找出如何按排序顺序检索行。排序是通过根据连接类型遍历所有行并将排序键和指针存储到与该 WHERE 子句匹配的所有行的行来完成的。然后对键进行排序,并按排序顺序检索行
  • Using index 仅使用索引树中的信息从表中检索列信息,而不必另外寻找读取实际行。当查询仅使用属于单个索引的列时,可以使用此策略。
  • Using index condition  通过首先访问索引,确定是否可以读取完整的表行。
  • Using index for group-by  使用索引分组。表示 MySQL 找到了一个索引,可用于检索 GROUP BY 或 DISTINCT 查询的所有列,而无需对实际表进行任何额外的磁盘访问。此外,索引以最有效的方式使用,因此对于每个组,只读取少数索引条目。
  • Using index for skip scan  使用索引跳过扫描范围
  • Using join buffer  将表数据读入缓存,然后从缓存中读数据来执行操作。
  • Using MRR 使用多范围读取优化策略读取表。
  • Using temporary 使用临时表,MySQL 需要创建一个临时表来保存结果。如果查询包含以不同方式列出列的 GROUP BY 和 ORDER BY 子句,则通常会发生这种情况。
  • Using where  使用上了 where 限制,表示 MySQL 服务器在存储引擎受到记录后进行“后过滤”(Post-filter),如果查询未能使用索引,Using where 的作用只是提醒我们 MySQL 将用 where 子句来过滤结果集。
  • Zero limit  查询有一个 LIMIT 0 子句,不能选择任何行。
  • Only index  这意味着信息只用索引树中的信息检索出的,这比扫描整个表要快。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计4408字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中