explain 各字段介绍

explain 是 sql 优化的利器,除了优化慢 sql,平时的 sql 编写,也应该先 explain,查看一下执行计划,看看是否还有优化的空间。

直接在 select 语句之前增加 explain 关键字,就会返回执行计划的信息。

如图所示,explain 中包含的信息有:

id:查询序列号

MySQL 会为每个 select 语句分配一个唯一的 id 值,用来表示查询中执行 select 子句或者操作表的顺序。如果只是单纯的查一个表,那么 id 就是 1。如果多表查询且 id 值相同,表示查询的优先级也是相同的,那么执行顺序即为从上到下,常见于子查询;如果 id 不同,如果是子查询,id 的序号会递增,id 值越大表示优先级越高,越先被执行;如果同时存在 id 相同和不同的,则相同的 id 可以认为是一组,从上往下顺序执行,在所有组中,id 值越大,优先级越高,越先执行。

select_type:查询类型。主要用来分辨查询的类型事普通查询还是联合查询还是子查询。常见的查询类型有:

  • simple:简单的查询,不包含子查询和 union
  • primary:查询中若包含任何复杂的子查询,最外层查询则被标记为 primary
  • union:在 union、union all 和子查询中的第二个和随后的 select 会被标记为 union
  • dependent union:在包含 union 或者 union all 的大查询中,如果各个小查询都依赖于外层查询的话,那除了最左边的那个小查询之外,其余的小查询的 select_type 的值就是 dependent union
  • union result:从 union 表获取结果的 select 会被标记为 union result
  • sebquery:在 select 或者 where 列表中包含子查询(不在from子句中)
  • dependent sebquery:子查询中的第一个 select(不在 from 子句中),并且取决于外层查询
  • derived:在 form 列表中包含的子查询被标记为 derived,也叫做派生类
  • uncacheable sebquery:一个子查询的结果不能被缓存
  • uncacheable union:表示 union 的查询结果不能被缓存

table:表示 explain 语句正在访问哪个表,表名或者别名,可能是临时表或者 union 合并结果集。如果是具体的表名,则表明从实际的物理表中获取数据,当然也可以是表的别名;表名是 derivedN 的形式,表示使用了 id 为 N 的查询所产生的衍生表;当有 union result 的时候,表名是union n1,n2 等的形式,n1,n2 表示参与 union 的 id.

type:访问类型,表示以何种方式去访问数据库,最容易想的是全表扫描,即直接暴力的遍历一张表去寻找需要的数据,效率非常低下。

访问的类型有很多,效率从最好到最坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

  • system:表只有一行记录(等于系统表),这是 const 类型的特例,平时不会出现,不需要进行磁盘 io
  • const:最多只能匹配到一条数据,通常使用主键或唯一索引进行等值条件查询
  • eq_ref:当进行等值联表查询使用主键索引或者唯一性非空索引进行数据查找时(实际上唯一索引等值查询 type 不是 eq_ref 而是 const)
  • ref:使用了非唯一性索引进行数据的查找
  • ref_or_null:对于某个字段既需要关联条件,也需要 null 值的情况下,查询优化器会选择这种访问方式
  • index_merge:在查询过程中需要多个索引组合使用
  • unique_subquery:该连接类型类似于 index_subquery,使用的是唯一索引。大多数情况下使用 SELECT 子查询时,MySQL 查询优化器会自动将子查询优化为联表查询,因此 type 不会显示为  index_subquery,而是 eq_ref
  • index_subquery:利用索引来关联子查询,不再扫描全表。但是大多数情况下使用 SELECT 子查询时,MySQL 查询优化器会自动将子查询优化为联表查询,因此 type 不会显示 index_subquery,而是 ref
  • range:表示利用索引查询的时候限制了范围,在指定范围内进行查询,这样避免了 index 的全索引扫描。适用的操作符:=, <>, >, >=, <, <=, is null, between,like, or, in
  • index:全索引扫描这个比 all 的效率要好,主要有两种情况,一种是当前的查询覆盖索引,即需要的数据在索引中就可以索取,或者是使用了索引进行排序,这样就避免了数据的重排序
  • all:全表扫描,需要扫描整张表,从头到尾找到需要的数据行。一般情况下出现这样的 sql 语句而且数据量比较大的话那么就需要进行优化

一般情况下,要保证查询至少达到 range 级别,最好能达到 ref

possible_keys:显示查询可能使用哪些索引来查找,即显示可能应用在这张表中的索引,一个或多个,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用

key:这一列显示 mysql 实际采用哪个索引来优化对该表的访问,即实际使用的索引,如果为 null ,则表示没有使用索引

key_len:表示索引中使用的字节数,可以通过 key_len 计算查询中使用的索引长度,在不损失精度的情况下长度越短越好。索引越大占用存储空间越大,这样 io 的次数和量就会增加,影响执行效率

ref:显示之前的表在 key 列记录的索引中查找值所用的列或者常量

rows 列:根据表的统计信息及索引使用情况,大致估算出找出所需记录需要读取的数据行数,此参数很重要,直接反应 sql 找了多少数据,在完成目的的情况下越少越好

filtered:针对表中符合某个条件(where 子句或者连接条件)的记录数的百分比所做的一个悲观估算

extra 列:显示不适合在其它列的额外信息,虽然叫额外,但是也有一些重要的信息:

  • using filtersort:说明 mysql 无法利用索引进行排序,只能利用排序算法进行排序,会消耗额外的位置
  • using index:表示当前的查询是覆盖索引的,直接从索引中读取数据,而不用访问数据表。如果同时出现 using where,表示索引被用来执行索引键值的查找,如果没有,表示索引被用来读取数据,而不是真的查找
  • using where:使用 where 进行条件过滤
  • using temporary :建立临时表来保存中间结果,查询完成之后把临时表删除
  • using join buffer:使用连接缓存
  • impossible where:where 语句的结果总是 false

本文参考自:MySQL进阶系列: 一文详解explain各字段含义 - 掘金

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值