Explain性能分析
1、explain的基本介绍
有时候我们可能需要知道 mysql 是如何解析执行我们的 SQL 语句的,比如有时候某些语句写在前面并不一定意味着它就会先执行,有没有使用到索引等待,此时我们可以通过 explain 语句来分析出 SQL 优化器是如何解析执行我们的 SQL 语句的。
使用 EXPLAIN 关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理你的 SQL 语句的,explain 主要用于分析查询语句或表结构的性能瓶颈。
1.1、explain的作用
通过explain+sql语句可以知道如下内容:
- 表的读取顺序(对应id)。
- 数据读取操作的操作类型(对应select_type)。
- 哪些索引可以使用(对应possible_keys)。
- 哪些索引被实际使用(对应key)。
- 表直接的引用(对应ref)。
- 每张表有多少行被优化器查询(对应rows)。
2、explain的基本使用
使用 explain 关键字来分析 SQL 语句的性能,只需要在 SQL 语句的前面加上 explain 即可,语法如下:
explain sql语句; -- 示例 explain select * from tbl_emp,tbl_dept where tbl_emp.deptId = tbl_dept.id;
执行结果:
3、explain的字段意思
使用 expain 分析 SQL 性能时,列出来的信息有10列,分别是id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra。
概要描述:
- id:表的读取顺序
- select_type:数据读取操作的操作类型。
- table:该查询是基于哪张表的
- partitions:匹配的分区
- type:表示表的连接类型
- possible_keys:哪些索引可以使用
- key:哪些索引被实际使用
- key_len:索引字段的长度
- ref:表直接的引用
- rows:扫描出的行数(估算的行数)
- filtered:按表条件过滤的行百分比
- Extra:执行情况的描述和说明
3.1、id(表的读取顺序)
explain 分析出来的 id 字段表示查询中执行 select 子句或操作表的顺序。比如,当查询的 SQL 语句涉及到多个表时,explain 分析出来的数据就有多条,其中 id 值越大的,表示SQL优化器会越早执行这个表。
其中,有三种情况:id全部相同、id全部不同、id部分相同。
3.1.1、id全部相同(执行顺序由上至下)
比如我们执行 explain 来分析某条SQL语句,其中涉及到三个表。如下图:
可以看到结果中,id全部都相同,此时意味着 SQL 优化器的执行顺序为由上至下。也就是 SQL 优化器实际上的执行计划是:先执行 t1 表的查询,再执行 t3 表,最后执行 t2 表。
3.1.2、id全部不同(id越大,越先被执行)
比如我们执行 explain 来分析某条SQL语句,其中涉及到三个表。如下图:
可以看到结果中,id全部不同,id 值越大优先级越高,越先被执行。也就是 SQL 优化器实际上的执行计划是:先执行 t3 表的查询,再执行 t2 表,最后执行 t1 表。
一般当涉及到子查询时,id 的序号会递增,id 值越大优先级越高,越先被执行.
3.1.3、id部分相同(相同id由上至下执行)
比如我们执行 explain 来分析某条SQL语句,其中涉及到三个表。如下图:
可以看到结果中,id部分相同,部分不同,此时仍然适用 id 值越大越先被执行的原则,id 相同的可以认为是同一组,从上往下顺序执行。也就是 SQL 优化器实际上的执行计划是:先执行 t3 表的查询,再执行衍生表 derived2,最后执行 t2 表。
(衍生表 derived2 的意思是该衍生表是 id 为2,即 t3 表的虚拟表)
3.2、select_type(查询操作的类型)
select_type 代表查询的类型,主要是用于区别普通查询、联合查询、子查询等的复杂查询。
select_type 的值和含义如下:
- SIMPLE:简单的 select 查询,查询中不包含子查询或者 UNION。
- PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为 Primary。
- DERIVED:在 FROM 列表中包含的子查询被标记为 DERIVED(衍生) MySQL 会递归执行这些子查询,,把结果放在临时表里。
- SUBQUERY:在SELECT或WHERE列表中包含了子查询。
- DEPEDENT SUBQUERY:在SELECT或WHERE列表中包含了子查询,子查询基于外层。
都是 where 后面的条件,subquery 是单个值,dependent subquery 是一组值。
- UNCACHEABLE SUBQUERY:无法使用缓存的子查询。
当使用了@@来引用系统变量的时候,不会使用缓存。
- UNION:若第二个SELECT出现在UNION之后,则被标记为UNION; 若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED。
- UNION RESULT:从UNION表获取结果的SELECT。