Mysql 执行计划

1. Explain 命令

Explain 可用来分析SQL的执行计划。字段含义如下:

列名 JSON 名称 意义
id select_id SELECT标识符
select_type SELECT类型
table table_name 输出行的表
partitions partitions 匹配的分区
type access_type 连接类型
possible_keys possible_keys 可供选择的指标
key key 实际选择的指标
key_len key_length 所选密钥的长度
ref ref 与索引相比的列
rows rows 估计要检查的行
filtered filtered 按表条件过滤的行的百分比
Extra 附加信息

1. id

SELECT 的执行编号,标识 sql 语句执行的顺序。

  • 数字越大越先执行,数字相同,从上往下依次执行
  • 无嵌套时,一般都是1,嵌套查询时会顺序编号,对应于其在原始语句中的位置
  • 值可能为 NULL ,如果这一行用来说明的是其他行的联合结果

2. select_type

查询类型,用于区分是普通查询、子查询或联合查询。

类型 说明
SIMPLE 简单子查询,不包含子查询和联合查询
PRIMARY 包含联合查询或者子查询中,最外层的查询
UNION 位于 union 中第二个及其后的子查询被标记为 UNION,第一个就被标记为 PRIMARY,如果是 union 位于 from 中则标记为 DERIVED
DEPENDENT UNION UNION 中依赖了外部查询的
UNION RESULT 从 union 中获取结果的查询
SUBQUERY 在 select 或者 where 列表中包含子查询,并且不在 from 子句中
DEPENDENT SUBQUERY SUBQUERY 中依赖了外部查询的
DERIVED 在 form 中包含的子查询, MySQL 会递归将其放在临时表中,称为派生表
DEPENDENT DERIVED DERIVED 中依赖了外部查询的
MATERIALIZED 物化子查询
UNCACHEABLE SUBQUERY 一个子查询的结果不能被缓存
UNCACHEABLE UNION 表示 union 的查询结果不能被缓存

3. table

表示当前这一行正在访问的表名或别名,可能是临时表或者 union 合并结果集。

  • 关联优化器会为查询选择关联顺序,左侧深度优先
  • 当 from 中有子查询时,表名是 <derivedN> 的形式,N 指向子查询,也就是 explain 结果中的下一列
  • 当有 UNION RESULT 时,表名是 <unionM,N> 等的形式,M,N 表示参与 union 的查询 id
  • 当引用值为物化子查询时,表名是 <subqueryN> 的形式,N 是子查询 id

4. partitions

当前查询匹配记录的分区,无分区表,返回 NULL 。

5. type(重点)

连接类型,表示以何种方式去访问数据库,性能从好到坏排序如下:

  • system:表仅有一行(相当于系统表),是 const 类型的特列。
  • const:表最多有一个匹配行,是针对主键或唯一索引的等值查询扫描。查询速度非常快, 因为它仅仅读取一次即可。
  • eq_ref:当进行等值联表查询使用主键索引或者唯一非空索引进行数据查询。
  • ref:当满足索引的最左前缀规则,或索引不是主键也不是唯一索引时用到。
  • fulltext:全文索引。
  • ref_or_null:类似于 ref,但会额外搜索哪些行包含了 NULL,常见于解析子查询。
  • index_merge:表示使用了索引合并优化,表示一个查询里面用到了多个索引。
  • unique_subquery:类似于 eq_ref ,但是使用了 in 查询,且子查询是主键或者唯一索引。
  • index_subquery:类似于 unique_subquery ,只是子查询使用的是非唯一索引。
  • range:范围扫描,表示检索了指定范围的行,主要用于有限制的索引扫描。如带有 between 子句或 where 子句里有 >、>=、<、<=、is null、<=>、between、like、in 等操作符
  • index:全索引扫描,当查询仅使用索引中的一部分列时,会使用此类型,有两种情况:
    • 如果索引是查询的覆盖索引,并且索引查询的数据就可以满足查询中所需的所有数据,则只扫描索引树
    • 按索引的顺序来查找数据行,执行了全表扫描
  • ALL:全表扫描。

6. possible_keys

展示当前查询可以使用哪些索引,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。

7. key

表示 MySQL 实际选择的索引。NULL 表示没有选择索引。

8. key_len

显示 MySQL 决定使用的键长度。如果键是 NULL,则长度为 NULL。在不损失精确性的情况下,使用的索引长度越短越好。

9. ref

一般是列名或 const ,表示将哪个字段或常量和键列所使用的字段进行比较。如果 ref 是一个函数,则使用的值是函数的结果。

10. rows(重点)

显示 MySQL 估算会扫描的行数,数值越小越好。

11. filtered

表示引擎返回的数据经过滤后满足查询条件记录数量的百分比,最大为 100。用 rows × filtered 可获得和下一张表连接的行数,如 rows = 1000,filtered = 50%,则和下一张表连接的行数是 500。

12. Extra

显示 MySQL 在查询过程中的一些详细信息,常见的有:

  • using where:使用 where 进行条件过滤
  • using index:表示当前的查询是覆盖索引的,直接从索引中读取数据
  • using temporary:建立临时表来保存中间结果,查询完成之后把临时表删除,常用于 group by 和 order by 操作中
  • using filtersort:说明 MySQL 无法利用索引进行排序,只能利用排序算法进行排序
  • using join buffer:使用连接缓存
  • impossible where:where 语句的结果总是 false,不会命中任何行
  • impossible having:having 语句的结果总是 false,不会命中任何行