这次是真拯救了我,MySQL 索引优化,explain 讲得非常清楚了 - 今日头条

本文由 简悦 SimpRead 转码, 原文地址 www.toutiao.com

在没有 GROUPBY 子句的情况下,基于索引优化 MIN/MAX 操作或者 对于 MyISAM 存储引擎优化 COUNT 操作,不必等到执行阶段

前言:

这篇文章主要讲 explain 如何使用,还有 explain 各种参数概念,之后会讲优化

模拟 Mysql 优化器是如何执行 SQL 查询语句的,从而知道 Mysql 是如何处理你的 SQL 语句的。分析你的查询语句或是表结构的性能瓶颈。

语法:Explain + SQL 语句;

如:Explain select * from user; 会生成如下 SQL 分析结果,下面详细对每个字段进行详解

https://p3.toutiaoimg.com/origin/pgc-image/4ef51324f7f5432c8718ffa76b2101a8.png?from=pc

是一组数字,代表多个表之间的查询顺序,或者包含子句查询语句中的顺序,id 总共分为三种情况,依次详解

  • id 相同,执行顺序由上至下
  • id 不同,如果是子查询,id 号会递增,id 值越大优先级越高,越先被执行
  • id 相同和不同的情况同时存在

select_type 包含以下几种值

  • simple
  • primary
  • subquery
  • derived
  • union
  • union result

simple

简单的 select 查询,查询中不包含子查询或者 union 查询

https://p3.toutiaoimg.com/origin/pgc-image/24513824a484466e82bd4e361311974e.png?from=pc

primary

如果 SQL 语句中包含任何子查询,那么子查询的最外层会被标记为 primary

https://p3.toutiaoimg.com/origin/pgc-image/4342b69635ce487198426e8f979135f5.png?from=pc

subquery

在 select 或者 where 里包含了子查询,那么子查询就会被标记为 subQquery,同三. 二同时出现

https://p3.toutiaoimg.com/origin/pgc-image/4fec3951d3ca465b9abbccbe304bb547.png?from=pc

derived

在 from 中包含的子查询,会被标记为衍生查询,会把查询结果放到一个临时表中

https://p3.toutiaoimg.com/origin/pgc-image/9eb9d9ac8fc249fc86da037fd9912f0f.png?from=pc

union / union result

如果有两个 select 查询语句,他们之间用 union 连起来查询,那么第二个 select 会被标记为 union,union 的结果被标记为 union result。它的 id 是为 null 的

https://p3.toutiaoimg.com/origin/pgc-image/524c4a103a044c50a78f155fcc442ec4.png?from=pc

表示这一行的数据是哪张表的数据

type 是代表 MySQL 使用了哪种索引类型,不同的索引类型的查询效率也是不一样的,type 大致有以下种类

  • system
  • const
  • eq_ref
  • ref
  • range
  • index
  • all

system

表中只有一行记录,system 是 const 的特例,几乎不会出现这种情况,可以忽略不计

const

将主键索引或者唯一索引放到 where 条件中查询,MySQL 可以将查询条件转变成一个常量,只匹配一行数据,索引一次就找到数据了

https://p3.toutiaoimg.com/origin/pgc-image/af274686b5b146209cf4faeb2ea1f86f.png?from=pc

eq_ref

在多表查询中,如 T1 和 T2,T1 中的一行记录,在 T2 中也只能找到唯一的一行,说白了就是 T1 和 T2 关联查询的条件都是主键索引或者唯一索引,这样才能保证 T1 每一行记录只对应 T2 的一行记录

举个不太恰当的例子,EXPLAIN SELECT * from t1 , t2 where t1.id = t2.id

https://p3.toutiaoimg.com/origin/pgc-image/0e47a632c90b48a799ea7ceac78af979.png?from=pc

ref

不是主键索引,也不是唯一索引,就是普通的索引,可能会返回多个符合条件的行。

https://p3.toutiaoimg.com/origin/pgc-image/2595bdf39b5d49c8aa347115b0d82d2f.png?from=pc

range

体现在对某个索引进行区间范围检索,一般出现在 where 条件中的 between、and、<、>、in 等范围查找中。

https://p3.toutiaoimg.com/origin/pgc-image/317b8522663e47619287485f304cb149.png?from=pc

index

将所有的索引树都遍历一遍,查找到符合条件的行。索引文件比数据文件还是要小很多,所以比不用索引全表扫描还是要快很多。

all

没用到索引,单纯的将表数据全部都遍历一遍,查找到符合条件的数据

此次查询中涉及字段上若存在索引,则会被列出来,表示可能会用到的索引,但并不是实际上一定会用到的索引

此次查询中实际上用到的索引

表示索引中使用的字节数,通过该属性可以知道在查询中使用的索引长度,注意:这个长度是最大可能长度,并非实际使用长度,在不损失精确性的情况下,长度越短查询效率越高

显示关联的字段。如果使用常数等值查询,则显示 const,如果是连接查询,则会显示关联的字段。

https://p3.toutiaoimg.com/origin/pgc-image/b3d84779d71e4edaa6e48b89c080a568.png?from=pc

  • tb_emp 表为非唯一性索引扫描,实际使用的索引列为 idx_name,由于 tb_emp.name=‘rose’为一个常量,所以 ref=const。
  • tb_dept 为唯一索引扫描,从 sql 语句可以看出,实际使用了 PRIMARY 主键索引,ref=db01.tb_emp.deptid 表示关联了 db01 数据库中 tb_emp 表的 deptid 字段。

根据表信息统计以及索引的使用情况,大致估算说要找到所需记录需要读取的行数,rows 越小越好

不适合在其他列显示出来,但在优化时十分重要的信息

using fileSort(重点优化)

俗称 “文件排序” ,在数据量大的时候几乎是 “九死一生”,在 order by 或者在 group by 排序的过程中,order by 的字段不是索引字段,或者 select 查询字段存在不是索引字段,或者 select 查询字段都是索引字段,但是 order by 字段和 select 索引字段的顺序不一致,都会导致 fileSort

https://p3.toutiaoimg.com/origin/pgc-image/f09904f027274c859016ebbb958a37b2.png?from=pc

using temporary(重点优化)

使用了临时表保存中间结果,常见于 order by 和 group by 中。

https://p3.toutiaoimg.com/origin/pgc-image/24648e119a2747dfb52747f1ceda932a.png?from=pc

USING index(重点)

表示相应的 select 操作中使用了覆盖索引(Coveing Index), 避免访问了表的数据行,效率不错! 如果同时出现 using where,表明索引被用来执行索引键值的查找;如果没有同时出现 using where,表面索引用来读取数据而非执行查找动作。

https://p3.toutiaoimg.com/origin/pgc-image/60ae097c24484bc5b2ed850ea757fb56.png?from=pc

Using wher

表明使用了 where 过滤

using join buffer

使用了连接缓存

impossible where

where 子句的值总是 false,不能用来获取任何元组

select tables optimized away

在没有 GROUPBY 子句的情况下,基于索引优化 MIN/MAX 操作或者 对于 MyISAM 存储引擎优化 COUNT(*) 操作,不必等到执行阶段再进行计算, 查询执行计划生成的阶段即完成优化。

distinct

优化 distinct,在找到第一匹配的元组后即停止找同样值的工作

作者:IT 老哥

链接: https://juejin.im/post/5f0535dae51d45348d39ffbe

来源:掘金