理解索引:MySQL执行计划详细介绍
为什么80%的码农都做不了架构师?>>>
最近有个需求,要修改现有存储结构,涉及查询条件和查询效率的考量,看了几篇索引和HBase相关的文章,回忆了相关知识,结合项目需求,说说自己的理解和总结。
前2篇介绍了索引的优点、索引结构的演化过程以及SQL的执行过程,重点分析了SQL的执行顺序和数据的定位过程,错过的朋友可以先回顾下:
- 索引结构和数据定位过程
- 查询过程和高级查询
这篇进入正题,介绍如何查看和分析SQL执行情况、排查SQL的性能问题,通过本篇介绍,你会了解到:
- explain命令概述
- select_type字段详细介绍
- type字段详细介绍
- extra字段详细介绍
部分内容摘录了几个博友的文章,最后会给出文章链接,感谢他们的精彩分析。
explain命令概述
工作中,MySQL会记录执行时间比较久的SQL语句,找出这些SQL语句是第一步,重要的是查看SQL语句的执行计划,对于MySQL执行计划的获取,可以通过explain方式来查看,这条命令的输出结果能够让我们了解MySQL优化器是如何执行SQL语句的。
MySQL优化器是基于开销来工作的,是在每条SQL语句执行的时候动态地计算出来的,命令用法十分简单, 在 SELECT 语句前加上 Explain 就可以了。
先来个示例
以基本的员工表为例,表的结构如下:
mysql> show create table employee \G;
*************************** 1. row ***************************Table: mcc_employee
Create Table: CREATE TABLE `employee` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`userId` varchar(50) DEFAULT NULL COMMENT '员工编号',`userName` varchar(50) DEFAULT NULL COMMENT '员工名称',`nickName` varchar(50) DEFAULT NULL COMMENT '昵称',`gender` varchar(10) DEFAULT NULL COMMENT '性别',`mobilePhone` varchar(20) DEFAULT NULL COMMENT '手机号',`miliao` varchar(100) DEFAULT NULL COMMENT '米聊号',`email` varchar(100) DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
一个简单的查询:
mysql> explain select * from employee where id =1 \G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: employeetype: const
possible_keys: PRIMARYkey: PRIMARYkey_len: 8ref: constrows: 1Extra: NULL
1 row in set (0.00 sec)
select_type为simple说明是一个普通的查询,不包含子查询和union查询。
字段概述
id字段:select查询的标识符. 每个select都会自动分配一个唯一的标识符,id数值越大的优先执行,id相同的从上往下顺序执行。
select_type:select查询的类型,当没有子查询或union查询时为simple,有子查询或union查询时,有几种情况,后面会详细介绍。
table:标识查询的是哪个表,显示这一行的数据是关于哪张表的,有时不是真实的表名字,看到的是derived<n>(n是个数字,为id字段)
mysql> explain select * from (select * from (select * from employee where id =76) table1 ) table2 ;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | NULL |
| 2 | DERIVED | <derived3> | system | NULL | NULL | NULL | NULL | 1 | NULL |
| 3 | DERIVED | mcc_inform | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
type:数据访问、读取操作类型,对性能影响比较大,后面会详细介绍。
possible_keys:此次查询中可能选用的索引,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。
key:此次查询中确切使用到的索引,如果没有选择索引,键是NULL。
key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。
ref: 哪个字段或常数与key一起被使用。
rows: 此查询一共扫描了多少行,这个是一个估计值。
filtered: 表示此查询条件所过滤的数据的百分比。
extra: 额外的信息,后面会详细介绍。
select_type字段详细介绍
select_type表示查询的类型,是简单查询或复杂查询,如果是复杂查询,包含SIMPLE、SIMPLE、UNION、UNION RESULT、SUBQUERY、DEPENDENT、DEPENDENT UNION、DEPENDENT SUBQUERY、DERIVED等,了解这些,可以识别在执行那部分。
SIMPLE
简单select,不使用union或子查询等:
mysql> explain select * from employee where id =1 ;
+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------+
SIMPLE
如果是复杂查询,表示是最外层的select:
mysql> explain select * from (select * from employee where id =1) a ;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | NULL |
| 2 | DERIVED | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
UNION & UNION RESULT
UNION中的第二个或后面的SELECT语句,UNION RESULT为UNION的结果:
mysql> explain select * from employee where id =1 union all select * from employee where id=2;
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-----------------+
| 1 | PRIMARY | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
| 2 | UNION | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
| NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------+------------+-------+---------------+---------+---------+-------+------+-----------------+
SUBQUERY
子查询中的第一个SELECT:
mysql> explain select * from employee where id = (select id from employee where id =1);
+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------------+
| 1 | PRIMARY | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
| 2 | SUBQUERY | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | Using index |
+----+-------------+------------+-------+---------------+---------+---------+-------+------+-------------+
DEPENDENT UNION & DEPENDENT SUBQUERY
DEPENDENT UNION,UNION中的第二个或后面的SELECT语句,但结果取决于外面的查询; DEPENDENT SUBQUERY,子查询中的第一个SELECT,但结果取决于外面的查询:
mysql> explain select * from employee where id in (select id from employee where id =1 union all select id from employee where id=2);
+----+--------------------+------------+-------+---------------+---------+---------+-------+------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+-------+---------------+---------+---------+-------+------+-----------------+
| 1 | PRIMARY | employee | ALL | NULL | NULL | NULL | NULL | 26 | Using where |
| 2 | DEPENDENT SUBQUERY | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | Using index |
| 3 | DEPENDENT UNION | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | Using index |
| NULL | UNION RESULT | <union2,3> | ALL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------------+------------+-------+---------------+---------+---------+-------+------+-----------------+
DERIVED
派生表的SELECT,FROM子句的子查询:
mysql> explain select * from (select * from employee where id =1) a ;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | NULL |
| 2 | DERIVED | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | NULL |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
type字段详细介绍
type表示数据访问/读取的操作类型,显示了连接使用了哪种类别,有无使用索引,它提供了判断查询是否高效的重要依据依据。
常见的类型有常用有,性能从差到好排序:ALL, index, range, ref, eq_ref, const, system, NULL
NULL
不用访问表或者索引就可以直接得到结果:
mysql> explain select sysdate();
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
const、system
如将主键或者唯一索引置于where列表中,MySQL就能将该查询转换为一个常量,当表中只有一行记录时,类型为system。
mysql> explain select * from (select id from mcc_inform where id =1) a;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | NULL |
| 2 | DERIVED | employee | const | PRIMARY | PRIMARY | 8 | const | 1 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+
eq_ref
此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较操作通常是 =, 查询效率较高:
mysql> explain select * from t3,t4 where t3.id=t4.accountid;
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
| 1 | SIMPLE | t4 | ALL | NULL | NULL | NULL | NULL | 1000 | |
| 1 | SIMPLE | t3 | eq_ref | PRIMARY,idx_t3_id | idx_t3_id | 4 | dbatest.t4.accountid | 1 | |
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
ref
与eq_ref类似,不同的是ref不是唯一索引,此类型通常出现在多表的 join 查询, 针对于非唯一或非主键索引, 或者是使用了最左前缀规则索引的查询,可以用于使用=或<=>操作符的带索引的列:
index_merge
该联接类型表示使用了索引合并优化方法, where中可能有多个条件(或者join)涉及到多个字段,它们之间进行 AND 或者 OR,那么此时就有可能会使用到 index merge 技术。
index merge 技术如果简单的说,其实就是:对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)。
range
表示使用索引范围查询, 通过索引字段范围获取表中部分数据记录, 这个类型通常出现在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中
index
表示全索引扫描(full index scan), 和 ALL 类型类似, 只不过 ALL 类型是全表扫描, 而 index 类型则仅仅扫描所有的索引, 而不扫描数据。
ALL
表示全表扫描, 这个类型的查询是性能最差的查询之一,一般不会出现。
extra字段详细介绍
EXplain中的很多额外的信息会在Extra字段显示,此字段能够给出让我们深入理解执行计划进一步的细节信息,介绍下常见的几个。
Using where
在查找使用索引的情况下,需要回表去查询所需的数据。
Using index
表示查询在索引树中就可查找所需数据, 不用扫描表数据文件, 说明性能不错。
Using filesort
当SQL中包含ORDER BY 操作,而且无法利用索引完成排序操作的时候,查询优化器不得不选择相应的排序算法来实现。
filesort主要用于查询数据结果集的排序操作,首先MySQL会使用sort_buffer_size大小的内存进行排序,如果结果集超过了sort_buffer_size大小,会把这一个排序后的chunk转移到file上,最后使用多路归并排序完成所有数据的排序操作。
filesort只能应用在单个表上,如果有多个表的数据需要排序,那么MySQL会先使用using temporary保存临时数据,然后再在临时表上使用filesort进行排序,最后输出结果。
Using temporary
查询有使用临时表, 一般出现于排序, 分组和多表join的情况, 查询效率不高, 建议优化.
下一篇文章会介绍索引优化原则以及案例分析。
参考文章:
- Mysql Explain 详解
- explain type连接类型示例
欢迎扫描下方二维码,关注我的个人微信公众号,查看更多文章 ~
转载于:https://my.oschina.net/qqtalk/blog/1823756
理解索引:MySQL执行计划详细介绍相关推荐
- 十、Mysql执行计划详细解析
Mysql执行计划详细解析 执行计划 什么是执行计划 执行计划的作用 执行计划的语法 执行计划详解 ID 列 Id 相同 Id 不同 Id 相同又不同 select_type 列 SIMPLE PRI ...
- mysql执行计划explain介绍_Mysql执行计划EXPLAIN详解
分析查询性能时,考虑EXPLAIN关键字同样很管用.EXPLAIN关键字一般放在SELECT查询语句的前面,用于描述MySQL如何执行查询操作.以及MySQL成功返回结果集需要执行的行数.explai ...
- MySQL 的索引、执行计划、优化器算法
SQL处理流程 INDEX 索引 索引介绍 索引:是排序的快速查找的特殊数据结构,定义作为查找条件的字段上,又称为键key,索引通过存储引擎实现: 索引相当于一本书的目录,可以优化查询. 优点: 索引 ...
- Mysql执行计划含义,mysql执行计划介绍
烂sql不仅直接影响sql的响应时间,更影响db的性能,导致其它正常的sql响应时间变长.如何写好sql,学会看执行计划至关重要.下面我简单讲讲mysql的执行计划,只列出了一些常见的情况,希望对大家 ...
- mysql 执行计划、索引、性能优化
一.逻辑架构 连接层:连接池.权限验证.服务器为每一个客户端请求创建一个线程或者分配一个空闲的线程(连接池),因此当多个请求(线程)共同操作同一个数据时可能会引起数据安全问题. 服务层:sql优化.缓 ...
- mysql执行计划extra为null_MySQL执行计划extra解析
MySQL执行计划extra解析 mysql的执行计划最让人难以捉磨的地方就是extra栏位的提示了,这是由于其他的 栏位没有提供详细的信息,因此多一个栏位来附加额外的信息,以利于用户更好的理解 sq ...
- Mysql学习总结(76)——MySQL执行计划(explain)结果含义总结
前言 对于MySQL执行计划的获取,我们可以通过explain方式来查看,explain方式看似简单,实际上包含的内容很多,尤其是输出结果中的type类型列.理解这些不同的类型,对于我们SQL优化举足 ...
- MySQL——执行计划
MySQL--执行计划 项目开发中,性能是我们比较关注的问题,特别是数据库的性能:作为一个开发,经常和SQL语句打交道,想要写出合格的SQL语句,我们需要了解SQL语句在数据库中是如何扫描表.如何使用 ...
- mysql 执行计划extra_MySQL执行计划extra中的using index 和 using where using index 的区别...
www.linuxidc.com/Linux/2017-- mysql执行计划中的extra列中表明了执行计划的每一步中的实现细节,其中包含了与索引相关的一些细节信息 其中跟索引有关的using in ...
最新文章
- phpstudy一个域名配置两个网站(一个是thinkphp5,一个是原生php)
- springboot的profile配置
- jQuery Mobile学习笔记
- ddos压力测试_蓝盟IT外包,浅析DDoS攻击防御和DDoS攻击原理
- JSON正确的下载网址及编译
- 编程c语言counter,c语言中计算平均分时,计数器(counter)的初始化
- Springboot 发邮件端口问题
- 微信 动画表情 骰子 猜拳
- 外国人申请在中国永久居留服务指南(中英文)
- 普中自动下载软件1.86下载程序失败
- 四轴自适应控制算法的一些尝试开源我的山猫飞控和梯度在线辨识自适应等算法—(转)
- Vue3 第十篇Plus:使用iconfont阿里巴巴矢量图标库
- kettle连接sap出现错误报错信息(127) JCO_ERROR_FIELD_NOT_FOUND : Field DATUM not a member of INPUT
- BlackHat USA 2021 洞察(三):议题技术解读
- 网络安全学习记录-13
- 人工智能:通过Python实现语音合成的案例
- 河工大大一c语言题库,河工大二级C语言题库.doc
- 局域网相关之交换机、VLAN、ARP、链路聚合技术
- win和linux双系统引导
- 2022年全球市场ERP系统服务研究报告