目录

一、概述

二、explain之id列介绍

三、explain之select_type列介绍

四、explain之table列介绍

五、explain之type列介绍

六、explain之possible_keys列与key列介绍

七、explain之key_len列介绍

八、explain之ref列介绍

九、explain之rows列介绍

十、explain之Extra列介绍

十一、执行计划案例分析

十二、总结


一、概述

我们在项目中或多或少会遇到一些性能瓶颈,比如服务器瓶颈、网络瓶颈、数据库瓶颈等,我们知道,数据库出现瓶颈更多是我们编写的SQL不好导致查询很慢。那么当我们遇到一条SQL查询慢时,我们应该如何去分析它,并且搞清楚MySQL是如何帮我们执行这条SQL的,这就要使用到我们今天介绍的EXPLAIN关键字。

  • 什么是执行计划?

在MySQL中,我们可以使用 EXPLAIN 关键字,获取MySQL如何执行SELECT语句的信息【包括在SELECT语句执行过程中表如何连接和连接的顺序】,从而知道MySQL是如何处理你的SQL语句的,分析你的查询语句或是表结构的性能瓶颈。MySQL官网对执行计划的介绍如下:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html。

  • 执行计划能帮我们完成什么事情?
  1. 查看表的读取顺序;
  2. 查看数据读取操作的操作类型;
  3. 查看哪些索引可以使用;
  4. 查看哪些索引被实际使用;
  5. 查看表之间的引用;
  6. 查看每张表有多少行被优化器查询;
  • 我们怎么使用执行计划?

我们可以使用【explain + SQL 语句】查看SQL的执行计划,执行计划里面包含信息主要有下面几列信息:

下面我们分别对EXPLAIN命令结果的每一列进行详细的说明。

二、explain之id列介绍

id:select 查询序列号,包含一组数字, 表示查询中执行 select 子句或操作表的顺序。id的值有三种:

  1. id 相同,执行顺序由上而下;
  2. id 不同,id 值越大优先级越高, 越先被执行;
  3. 一部分id相同,一部分id不同;

注意:如果id列为null的表示这是一个结果集,不需要使用它来进行查询。

下面详细分析每一种id值代表的select操作表的顺序:

  • id 相同,执行顺序由上而下

  • id 不同,如果是子查询,id 的序号会递增, id 值越大优先级越高, 越先被执行

  • id 相同不同,同时存在

id 如果相同,可以认为是一组的,从上往下执行;在所有组中,id 值越大,优先级越高,越先执行;

三、explain之select_type列介绍

select_type:表示查询的类型,主要是用于区别是普通查询,联合查询,子查询等。主要有以下一些值:

select_type 属性

含义

SIMPLE

表示不需要union操作或者不包含子查询的简单select查询。

PRIMARY

一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type即为primary

DERIVED

在 FROM 列表中包含的子查询被标记为 DERIVED(衍生) ,MySQL 会递归执行这些子查询, 把结果放在临时表里。

SUBQUERY

在SELECT或WHERE列表中包含了子查询,除了from子句中包含的子查询外,其他地方出现的子查询都可能是subquery

DEPEDENT SUBQUERY

在SELECT或WHERE列表中包含了子查询,子查询基于外层

UNCACHEABLE SUBQUERY

无法使用缓存的子查询

UNION

若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED

UNION RESULT

包含union的结果集,在union和union all语句中,因为它不需要参与查询,所以id字段为null

下面我们通过一些简单的示例看看如何通过执行计划看出查询的类型。

  • SIMPLE

SIMPLE 代表简单查询。

  • PRIMARY

PRIMARY表示查询中若包含任何复杂的子部分,最外层查询则被标记为 Primary。

  • DERIVED

DERIVED表示在 FROM 列表中包含的子查询被标记为 DERIVED(衍生),MySQL 会递归执行这些子查询,把结果放在临时表里。

  • SUBQUERY

SUBQUERY表示在 SELECT 或 WHERE 列表中包含了子查询。

  • DEPENDENT SUBQUERY

DEPENDENT SUBQUERY表示在 SELECT 或 WHERE 列表中包含了子查询,子查询基于外层。

  • UNION与UNION RESULT

UNION指的是若第二个 SELECT 出现在 UNION 之后,则被标记为 UNION;若 UNION 包含在 FROM 子句的子查询中,外层 SELECT将被标记为:DERIVED。

UNION RESULT表示从 UNION 表获取结果的 SELECT。

四、explain之table列介绍

table表示显示的查询表名,如果查询使用了别名,那么这里显示的是别名,如果不涉及对数据表的操作,那么这显示为null,如果显示为尖括号括起来的<derived N>就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。如果是尖括号括起来的<union M,N>,与<derived N>类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。

五、explain之type列介绍

type指的是访问类型, 是较为重要的一个指标,结果值从最好到最坏依次是:

system > const > eq_ref > ref > range > index > ALL ,一般来说,得保证查询至少达到 range 级别,最好能达到 ref。

更加详细的如下:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

下面我们依次来看一下各种访问类型的区别【效率从最好到最坏】。

  • system

system 表示表只有一行记录(等于系统表),这是 const 类型的特列,平时不会出现,这个也可以忽略不计。

  • const

const表示通过索引一次就找到了,查询起来非常迅速,常 用于比较 primary key 或者 unique 索引。 因为只匹配一行数据,所以很快,比如将主键置于where 列表中, MySQL 就能将该查询转换为一个常量。

  • eq_ref

eq_ref 表示对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描。

  • ref

ref表示非唯一性索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以ref应该属于查找和扫描的混合体。

  • range

range 表示只检索给定范围内的行,使用一个索引来选择行。key 列显示使用了哪个索引。一般就是在 where 语句中出现了 between、<、<=、>、>=、in 等的查询。这种范围扫描索引比全表扫描要好,因为它只需要开始于索引的某个点,而结束于另一个点,而不需要进行全表扫描。

  • index

index,全称是Full Index Scan,即索引全扫描 ,MySQL遍历整个索引来查询匹配行,并不会扫描表。 index 于 ALL的区别 ,index 类型只遍历索引树, 通常比 ALL 快, 因为索引文件通常比数据文件小。(也就是说虽然 all 和 index 都是读全表,但是index 是从索引中读取的, 而 all 是从硬盘中读取的 )。出现index是sql使用了索引但是没有通过索引进行过滤,一般是使用了覆盖索引或者是利用索引进行了排序分组。

  • ALL

ALL表示Full Table Scan ,即将遍历全表找到匹配的行,全表扫描,性能最差。

  • NULL

type=NULL,指的是MySQL不用访问表或者索引,直接就能够得到结果。

六、explain之possible_keys列与key列介绍

  • possible_keys:显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。如果该列为NULL,说明没有使用索引,可以对该列创建索引来提高性能。
  • key:表示实际使用的索引。如果为NULL,则没有使用索引。

注意:如果查询中若使用了覆盖索引,则该索引仅出现在KEY列表中。

七、explain之key_len列介绍

key_len表示索引中使用的字节数,可通过该列计算查询中的使用的索引的长度,在不损失精确性的情况下,长度越短越好。key_len 显示的只为索引字段的最大可能长度, 并非实际使用长度,即 key_len 是根据表定义计算而得,不是通过表内检索出的。

如上我们可以看到,查询条件越多,查询付出的代价也就越大,key_len 的长度就越大,建议在一定条件的情况下,key_len 越短,效率越高。

八、explain之ref列介绍

ref表示显示索引的哪一列被使用了,如果是使用的常数等值查询,ref会显示const,如果是连接查询,被驱动表的执行计划ref会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,ref可能显示为func。

如上图,我们可以看到t1表的dept_id匹配了 t2 表的 id,并且t1表的 name 匹配了一个常量即 ‘z3’。

九、explain之rows列介绍

rows 列显示 MySQL 认为它执行查询时执行计划中估算的扫描行数,不是精确值。MySQL执行引擎根据表统计信息及索引选用情况, 大致估算出找到所需的记录所需读取的行数,rows越少越好。

十、explain之Extra列介绍

Extra表示执行情况的说明和描述,包含不适合在其他列中显示但是对执行计划非常重要的额外信息。下面我们来看看有哪些重要的信息。最主要的有一下三种:

Using Index

表示索引覆盖,不会回表查询

Using Where

表示进行了回表查询

Using Index Condition

表示进行了ICP优化

Using Flesort

表示MySQL需额外排序操作, 不能通过索引顺序达到排序效果

  • Extra之Using filesort

Using filesort说明 mysql 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取,mysql 中无法利用索引完成的排序叫做 “文件排序”。

  • Extra之Using temporary

Using temporary使用了临时表保存中间结果, MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by 。

  • Extra之Using index

Using index表示相应的 select 操作使用了覆盖索引 (Covering Index),避免了访问表的数据行,效率不错。

  1. 如果同时出现 using where , 表示索引被用来执行索引键值的查找;
  2. 如果没有同时出现 using where , 表明索引用来读取数据而非执行查找动作;

这里介绍一下什么是覆盖索引?

覆盖索引 (Covering Index),就是 select 的数据列只用从索引中就能取得,不必读取数据行, MySQL 可以利用你索引返回 select 列表的字段, 而不必根据索引再次读取数据文件,换句话说查询列要被所建的索引覆盖。举个简单的例子:

tb_emp表建立了联合索引: idx_name_age_hobby
非覆盖索引:EXPLAIN SELECT * FROM `tb_emp` t1 WHERE t1.`name` = 'z3' AND t1.`age` = 20;
覆盖索引: EXPLAIN SELECT t1.`name`,t1.`age`, t1.`hobby` FROM `tb_emp` t1 WHERE t1.`name` = 'z3' AND t1.`age` = 20;

使用覆盖索引需要的注意的地方:

1)、如果要使用覆盖索引,一定要注意 select 列表汇总只取出需要的列,不要用 select * ;

2)、如果将所有字段一起做索引将会导致索引文件过大,查询性能下降;

  • Extra之Using Index Condition

表示进行了ICP优化。MySQL5.6引入了Index Condition Pushdown(ICP)的特性,进一步优化了查询。Pushdown表示操作下放,某些情况下的条件过滤操作下放到存储引擎,这样能够降低不必要的IO访问。

  • Extra之Using where

Using where表明使用了 where 过滤。

  • Extra之using join buffer

using join buffer使用了连接缓存。

  • Extra之impossible where

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

  • Extra之select tbale optimized away

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

  • Extra之distinct

distinct 指在select部分使用了distinc关键字,并优化 distinct 操作,在找到第一匹配的元组后立即停止找相同值的动作。

十一、执行计划案例分析

观察上述执行计划结果,我们分析一下整个查询的执行顺序和过程。根据id列的值,id越大的越先执行。所以我们可以知道,上述的执行顺序为:

4【扫描t2】 -> 3【扫描t1】 -> 2【扫描t3】 -> 1【扫描 <derived3>】 -> NULL【 <union1,4>】

下面是详细的执行过程:

  • 1)、第一行 (执行顺序4):id 列为1 , 表示 union 的第一个 select , select_type 的 primary 表表示该查询为外层查询, table 列被标记为 <derived3>,表示查询结果来自一个衍生表,其中 derived3 中的 3 代表查询衍生自第三个 select 查询, 即 id 为 3 的 【select [select d1.name......】
  • 2)、第二行(执行顺序为2):id 为 3 ,是整个查询中第三个 select 的一部分, 因查询包含在from 中, 所以为derived 。 【SELECT t1.`id`, t1.`name` FROM tb_emp t1 WHERE t1.`name` = 'z3'】
  • 3)、第三行(执行顺序为3):select 列表中的子查询 select_type 为 subquery , 为整个查询中的第二个 select。【SELECT t3.emp_id FROM tb_salary t3】
  • 4)、第四行(执行顺序为1):select_type 为 union , 说明第四个 select 是 union 里的第二个 select ,最先执行 【SELECT t2.id, t2.name FROM`tb_dept` t2】
  • 5)、第五行(执行顺序为5):代表 union 的临时表中读取行的阶段, table 列的 <union , 1, 4> 表示用第一个和第四个 select 结果进行union 操作 。 【两个结果 union 操作】

十二、总结

本篇文章主要总结了如何使用explain来分析我们的SQL语句,并对执行计划中每个内容进行了详细的介绍。在实际项目中,我们遇到执行很慢的SQL时,一般需要打开MySQL慢日志查询,找出慢SQL,然后再使用explain分析其执行计划以及索引使用情况,进而优化它。由于笔者水平有限,如文中有不对之处,还望指正,希望对大家有所帮助。

MySQL使用EXPLAIN查看SQL的执行计划相关推荐

  1. MySQL——通过EXPLAIN分析SQL的执行计划

    在MySQL中,我们可以通过EXPLAIN命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序. 下面分别对EXPLAIN命令结果的每一列进行说明: ...

  2. mysql查看执行计划_MySql中如何使用 explain 查询 SQL 的执行计划

    explain命令是查看查询优化器如何决定执行查询的主要方法. 这个功能有局限性,并不总会说出真相,但它的输出是可以获取的最好信息,值得花时间去了解,因为可以学习到查询是如何执行的. 1.什么是MyS ...

  3. explain如何查看mysql_MySql中如何使用 explain 查询 SQL 的执行计划

    explain命令是查看查询优化器如何决定执行查询的主要方法. 这个功能有局限性,并不总会说出真相,但它的输出是可以获取的最好信息,值得花时间去了解,因为可以学习到查询是如何执行的. 1.什么是MyS ...

  4. Oracle 查看sql语句执行计划方法

    注意这篇文章只介绍查看sql语句执行计划的方法, 并不是说明如何看懂执行计划. 一般来讲, 直接在sqlplus 执行 set autotrace on; 就可以了 其前提是登陆用户必须有视图  v_ ...

  5. 在 MySQL 中使用 explain 查询 SQL 的执行计划(转自: 数据分析与开发)

    **来源:Oo若离oO my.oschina.net/ruoli/blog/1807394** 1.什么是MySQL执行计划 要对执行计划有个比较好的理解,需要先对MySQL的基础结构及查询基本原理有 ...

  6. 在MySQL中使用explain查询SQL的执行计划

    1.什么是MySQL执行计划 要对执行计划有个比较好的理解,需要先对MySQL的基础结构及查询基本原理有简单的了解. MySQL本身的功能架构分为三个部分,分别是 应用层.逻辑层.物理层,不只是MyS ...

  7. MySQL调优系列:explain分析SQL的执行计划

    一条SQL的执行计划自我描述 [提前声明] 文章由作者:张耀峰 结合自己生产中的使用经验整理,最终形成简单易懂的文章 写作不易,转载请注明,谢谢! 大数据代码案例地址: https://github. ...

  8. Mysql学会查看sql的执行计划

    什么是执行计划? 首先在Mysql的服务中有连接器.查询缓存(Mysql8 已经删除).分析器.优化器.执行器等,所有跨存储引擎的功能都在这一层实现 而一条sql怎么执行是由优化器决定的, 优化器分为 ...

  9. expain 查看SQL的执行计划

    在日常工作中,我们会有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这些SQL语句并不意味着完事了,些时我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有 ...

  10. MySQL进阶之路(二十)—— 5分钟看懂SQL的执行计划

    5分钟看SQL的执行计划 一.概述 ​ 如果你想优化SQL语句,那么SQL执行计划就是必须要知道的,因为只有通过SQL的执行计划,你才可以知道SQL是如何进行查询的,以及否走索引.用的是什么索引.是否 ...

最新文章

  1. 终于有人把JAVA虚拟机讲清楚了!
  2. KDE应用如何在GNOME环境下运行?
  3. 软件工程导论-软件工程概论(学习笔记)
  4. 时频分析matlab实例,Matlab时频分析工具箱及仿真案例
  5. Windows系统下桌面右键菜单新建项管理
  6. 大学四年的收获及工作感悟
  7. PAAS平台的理解及与LaaS,SaaS的关系
  8. 解决Google-Chrome浏览器无法打开Kubernetes-K8S-Dashboard页面
  9. 华为Mate40和iPhone12网络舆情传播数据分析报告
  10. 美颜SDK全身美颜是基于什么技术实现的?
  11. MSM8953配置I2C及SPI
  12. 教师资格证面试 计算机应用,请问下,中职类教师资格证,科目是计算机应用。可..._教师招聘考试_帮考网...
  13. 知乎搜索排序模型的演进
  14. 数据泄漏检测和溯源技术
  15. 源码分析 RocketMQ DLedger 多副本存储实现,泛微网络java面试题
  16. spring--享学课堂
  17. linux下usb的热插拔监控,怎么linux下检测 usb摄像头热插拔事件
  18. tcmalloc的工作原理
  19. 指南:内网穿透与DDNS动态域名解析区别,一篇看懂
  20. 英特尔酷睿i3和i5的区别是什么?

热门文章

  1. ireport在Java中不展示_编译错误:ireport with java;属性'uuid'不允许出现在元素'jasperReport'中...
  2. 翻译: 全球导航卫星系统 (GNSS) 的演进
  3. 容器技术Docker K8s 12 容器服务Kubernetes版ACK详解-使用镜像快速创建无状态应用
  4. python3 读取文件夹的文件标题,提取小数,并计算数字和
  5. CondaHTTPError: HTTP 000 CONNECTION FAILED for url ...... 解决过程
  6. java算术表达式求值-中缀表达式转后缀表达式
  7. 现代通信原理7.1:模拟角度调制的基本概念
  8. hdu acm2549
  9. 计算机图形学完整笔记(五):二维图形变换
  10. unixlinux命令,20个 Unix/Linux 命令技巧