MySQL EXPLAIN输出列的详细解释


Posted in MySQL onMay 12, 2021

1. 简介

EXPLAIN语句提供有关 MySQL 如何执行语句的信息。

EXPLAIN与SELECT、DELETE、INSERT、REPLACE和UPDATE语句一起使用。

mysql> EXPLAIN SELECT * FROM employees WHERE emp_no = 10001;
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | employees | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

简单来讲,通过EXPLAIN可以分析出SQL语句走没走索引,走的是什么索引。

EXPLAIN为SELECT语句中使用的每个表返回一行信息,它按照 MySQL 在处理语句时读取它们的顺序列出了输出中的表。

MySQL 使用嵌套循环连接(Nested-Loop Join Algorithms)解析所有连接,这意味着 MySQL 从第一个表中读取一行,然后在第二个表,第三个表中找到匹配的行,依此类推。处理完所有表后,MySQL将通过表列表输出选定的列后回溯直到找到一个表,其中存在更多匹配的行。从该表中读取下一行,然后继续下一个表。

2.EXPLAIN 输出列

  • MySQL版本 5.7.33
  • Windows10 64位

从上图看到 EXPLAIN 的结果中,包括的表头id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、Extra,这些字段的意思我们来学习然后通过实例进行了解一下。

2.1 id

SELECT 标识符,查询中 SELECT 的顺序号。如果该行引用其他行的并集结果,则该值可以为NULL。在这种情况下,表列显示类似<unionM,N>的值,以指示该行引用 id 值为 M 和 N 的行的并集。

id 值分三种情况:

id 相同,执行顺序由上至下

mysql> EXPLAIN (
    -> SELECT * FROM employees emp
    -> LEFT JOIN dept_emp de ON emp.emp_no = de.emp_no
    -> LEFT JOIN departments dept ON dept.dept_no = de.dept_no
    -> WHERE emp.emp_no = 10001);
+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+------+----------+-------+
| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref                  | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+------+----------+-------+
|  1 | SIMPLE      | emp   | NULL       | const  | PRIMARY       | PRIMARY | 4       | const                |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | de    | NULL       | ref    | PRIMARY       | PRIMARY | 4       | const                |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | dept  | NULL       | eq_ref | PRIMARY       | PRIMARY | 12      | employees.de.dept_no |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+------+----------+-------+
3 rows in set, 1 warning (0.03 sec)

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

mysql> EXPLAIN SELECT * FROM employees emp
    -> WHERE emp.emp_no NOT IN ( SELECT de.emp_no FROM dept_emp de 
    -> WHERE de.dept_no NOT IN ( SELECT dept_no FROM departments WHERE dept_name = 'Development'));
+----+-------------+-------------+------------+-------+-------------------+-----------+---------+-------+--------+----------+--------------------------+
| id | select_type | table       | partitions | type  | possible_keys     | key       | key_len | ref   | rows   | filtered | Extra                    |
+----+-------------+-------------+------------+-------+-------------------+-----------+---------+-------+--------+----------+--------------------------+
|  1 | PRIMARY     | emp         | NULL       | ALL   | NULL              | NULL      | NULL    | NULL  | 299468 |   100.00 | Using where              |
|  2 | SUBQUERY    | de          | NULL       | index | PRIMARY           | dept_no   | 12      | NULL  | 308493 |   100.00 | Using where; Using index |
|  3 | SUBQUERY    | departments | NULL       | const | PRIMARY,dept_name | dept_name | 122     | const |      1 |   100.00 | Using index              |
+----+-------------+-------------+------------+-------+-------------------+-----------+---------+-------+--------+----------+--------------------------+
3 rows in set, 1 warning (0.00 sec)

id相同和不相同都存在

如果id相同可以认为是一组,同一组id执行顺序由上至下,不同组之间,id值越大被执行的优先级越高。

mysql> EXPLAIN SELECT * FROM employees emp
    -> WHERE emp.emp_no IN ( SELECT de.emp_no FROM dept_emp de 
    -> WHERE de.dept_no IN ( SELECT dept_no FROM departments WHERE dept_name LIKE '%Develop%'));
+----+--------------+-------------+------------+-------+-----------------+-----------+---------+-------------------------------+--------+----------+----------------------------------------------------+
| id | select_type  | table       | partitions | type  | possible_keys   | key       | key_len | ref                           | rows   | filtered | Extra                                              |
+----+--------------+-------------+------------+-------+-----------------+-----------+---------+-------------------------------+--------+----------+----------------------------------------------------+
|  1 | SIMPLE       | <subquery2> | NULL       | ALL   | NULL            | NULL      | NULL    | NULL                          |   NULL |   100.00 | NULL                                               |
|  1 | SIMPLE       | emp         | NULL       | ALL   | PRIMARY         | NULL      | NULL    | NULL                          | 299468 |     0.00 | Using where; Using join buffer (Block Nested Loop) |
|  2 | MATERIALIZED | departments | NULL       | index | PRIMARY         | dept_name | 122     | NULL                          |      9 |    11.11 | Using where; Using index                           |
|  2 | MATERIALIZED | de          | NULL       | ref   | PRIMARY,dept_no | dept_no   | 12      | employees.departments.dept_no |  38561 |   100.00 | Using index                                        |
+----+--------------+-------------+------------+-------+-----------------+-----------+---------+-------------------------------+--------+----------+----------------------------------------------------+
4 rows in set, 1 warning (0.01 sec)

2.2 select_type

查询的类型,主要用来区别普通查询,联合查询,子查询等复杂查询。

包含SIMPLE、PRIMARY、UNION、DEPENDENT UNION、UNION RESULT、SUBQUERY、DEPENDENT SUBQUERY、DERIVED、MATERIALIZED、UNCACHEABLE SUBQUERY、UNCACHEABLE UNION

SIMPLE

简单的SELECT,不使用UNION或子查询。

mysql> EXPLAIN select * from employees where emp_no=10001;
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | employees | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+-----------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

PRIMARY

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

mysql> EXPLAIN SELECT * FROM employees emp
    -> WHERE emp.emp_no IN ( SELECT max(emp_no) FROM dept_emp);
+----+--------------------+-------+------------+------+---------------+------+---------+------+--------+----------+------------------------------+
| id | select_type        | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra                        |
+----+--------------------+-------+------------+------+---------------+------+---------+------+--------+----------+------------------------------+
|  1 | PRIMARY            | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 299468 |   100.00 | Using where                  |
|  2 | DEPENDENT SUBQUERY | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL |   NULL |     NULL | Select tables optimized away |
+----+--------------------+-------+------------+------+---------------+------+---------+------+--------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

UNION

第二个或更靠后的 SELECT 语句出现在 UNION 之后,则被标记为 UNION

mysql> EXPLAIN (SELECT emp_no,dept_no FROM dept_emp LIMIT 10)
    -> UNION
    -> SELECT emp_no,dept_no FROM dept_manager;
+----+--------------+--------------+------------+-------+---------------+---------+---------+------+--------+----------+-----------------+
| id | select_type  | table        | partitions | type  | possible_keys | key     | key_len | ref  | rows   | filtered | Extra           |
+----+--------------+--------------+------------+-------+---------------+---------+---------+------+--------+----------+-----------------+
|  1 | PRIMARY      | dept_emp     | NULL       | index | NULL          | dept_no | 12      | NULL | 308493 |   100.00 | Using index     |
|  2 | UNION        | dept_manager | NULL       | index | NULL          | dept_no | 12      | NULL |     24 |   100.00 | Using index     |
| NULL | UNION RESULT | <union1,2>   | NULL       | ALL   | NULL          | NULL    | NULL    | NULL |   NULL |     NULL | Using temporary |
+----+--------------+--------------+------------+-------+---------------+---------+---------+------+--------+----------+-----------------+
3 rows in set, 1 warning (0.00 sec)

DEPENDENT UNION

与 UNION 相同,它出现在 UNION 或 UNION ALL语句中,但是此查询受外部查询的影响

| UNION RESULT union_result Result of a UNION.
| SUBQUERY None First SELECT in subquery
| DEPENDENT SUBQUERY dependent (true) First SELECT in subquery, dependent on outer query
| DERIVED None Derived table
| MATERIALIZED materialized_from_subquery Materialized subquery
| UNCACHEABLE SUBQUERY cacheable (false) A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query
| UNCACHEABLE UNION cacheable (false) The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)

总结

到此这篇关于MySQL EXPLAIN输出列的文章就介绍到这了,更多相关MySQL EXPLAIN输出列内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
MySQL主从复制断开的常用修复方法
Apr 07 MySQL
如何设计高效合理的MySQL查询语句
May 26 MySQL
MySQL中使用or、in与union all在查询命令下的效率对比
May 26 MySQL
Mysql中调试存储过程最简单的方法
Jun 30 MySQL
Mysql数据库中datetime、bigint、timestamp来表示时间选择,谁来存储时间效率最高
Aug 23 MySQL
mysql如何能有效防止删库跑路
Oct 05 MySQL
一条慢SQL语句引发的改造之路
Mar 16 MySQL
MySQL学习之基础操作总结
Mar 19 MySQL
MySQL Server 层四个日志
Mar 31 MySQL
MySQL的存储函数与存储过程的区别解析
Apr 08 MySQL
Windows下载并安装MySQL8.0.x 版本的完整教程
Apr 10 MySQL
mysql中如何用命令创建联合唯一索引
Apr 20 MySQL
MySQL 分页查询的优化技巧
May 12 #MySQL
MySql学习笔记之事务隔离级别详解
MySQL 分组查询的优化方法
May 12 #MySQL
JDBC连接的六步实例代码(与mysql连接)
May 12 #MySQL
MySQL索引知识的一些小妙招总结
MySQL COUNT函数的使用与优化
May 10 #MySQL
解读MySQL的客户端和服务端协议
You might like
session 的生命周期是多长
2006/10/09 PHP
php各种编码集详解和以及在什么情况下进行使用
2011/09/11 PHP
php 短链接算法收集与分析
2011/12/30 PHP
laravel学习教程之存取器
2016/07/30 PHP
thinkphp实现分页显示功能
2016/12/03 PHP
Laravel 队列使用的实现
2019/01/08 PHP
js String对象中常用方法小结(字符串操作)
2012/01/27 Javascript
js 字符串转换成数字的三种方法
2013/03/23 Javascript
IE下写xml文件的两种方式(fso/saveAs)
2013/08/05 Javascript
JS实现日期加减的方法
2013/11/29 Javascript
jQuery简单图表peity.js使用示例
2014/05/02 Javascript
jquery获取所有选中的checkbox实现代码
2016/05/26 Javascript
基于原生JS实现图片裁剪
2016/08/01 Javascript
轮播图组件js代码
2016/08/08 Javascript
在js里怎么实现Xcode里的callFuncN方法(详解)
2016/11/05 Javascript
JavaScript学习总结(一) ECMAScript、BOM、DOM(核心、浏览器对象模型与文档对象模型)
2018/01/07 Javascript
详解React开发必不可少的eslint配置
2018/02/05 Javascript
webpack的tree shaking的实现方法
2019/09/18 Javascript
node后端服务保活的实现
2019/11/10 Javascript
[47:42]Fnatic vs Liquid 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[58:59]完美世界DOTA2联赛PWL S3 access vs CPG 第一场 12.13
2020/12/16 DOTA
python中requests模块的使用方法
2015/04/08 Python
Python Tkinter Entry和Text的添加与使用详解
2020/03/04 Python
Python: glob匹配文件的操作
2020/12/11 Python
如何使用localstorage代替cookie实现跨域共享数据问题
2018/04/18 HTML / CSS
HTML5响应式(自适应)网页设计的实现
2017/11/17 HTML / CSS
size?德国官方网站:英国伦敦的球鞋精品店
2018/03/17 全球购物
JustFab加拿大:女鞋、靴子、手袋和服装在线
2018/05/18 全球购物
德国高尔夫商店:Golfshop.de
2019/06/22 全球购物
白酒业务员岗位职责
2013/12/27 职场文书
简历中自我评价怎么写
2014/02/12 职场文书
环卫工人慰问信
2015/02/15 职场文书
军训个人总结
2015/03/03 职场文书
2016年推广普通话宣传周活动总结
2016/04/06 职场文书
深度学习详解之初试机器学习
2021/04/14 Python
Python字符串对齐方法使用(ljust()、rjust()和center())
2021/04/26 Python