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 INSERT INTO语句
May 26 MySQL
MySQL 常见的数据表设计误区汇总
Jun 07 MySQL
浅谈MySQL之浅入深出页原理
Jun 23 MySQL
通过shell脚本对mysql的增删改查及my.cnf的配置
Jul 07 MySQL
MySQL令人大跌眼镜的隐式转换
Aug 23 MySQL
Mysql实现简易版搜索引擎的示例代码
Aug 30 MySQL
为什么MySQL 删除表数据 磁盘空间还一直被占用
Oct 16 MySQL
MySQL数据库优化之通过索引解决SQL性能问题
Apr 10 MySQL
聊聊mysql都有哪几种分区方式
Apr 13 MySQL
详解Mysq MVCC多版本的并发控制
Apr 29 MySQL
MySQL中JOIN连接的基本用法实例
Jun 05 MySQL
MySQL数据库表约束讲解
Jun 21 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
php preg_match_all结合str_replace替换内容中所有img
2008/10/11 PHP
非常实用的php弹出错误警告函数扩展性强
2014/01/17 PHP
PHP Static延迟静态绑定用法分析
2016/03/16 PHP
jquery 获取json数据实现代码
2009/04/27 Javascript
JQuery在页面中添加和除移DOM示例代码
2013/06/24 Javascript
jquery ajax 简单范例(界面+后台)
2013/11/19 Javascript
raphael.js绘制中国地图 地图绘制方法
2014/02/12 Javascript
jQuery实现选中弹出窗口选择框内容后赋值给文本框的方法
2015/11/23 Javascript
AngularJS使用带属性值的ng-app指令实现自定义模块自动加载的方法
2017/01/04 Javascript
利用js查找数组中指定元素并返回该元素的所有索引示例
2017/03/29 Javascript
angular 内存溢出的问题解决
2018/07/12 Javascript
vue-cli 3.0 版本与3.0以下版本在搭建项目时的区别详解
2018/12/11 Javascript
js滚轮事件 js自定义滚动条的实现
2020/01/18 Javascript
[04:32]玩具屠夫中文语音节选
2020/08/23 DOTA
在漏洞利用Python代码真的很爽
2007/08/26 Python
Python复制文件操作实例详解
2015/11/10 Python
举例讲解Python中的list列表数据结构用法
2016/03/12 Python
Python实现KNN(K-近邻)算法的示例代码
2019/03/05 Python
linux下安装python3和对应的pip环境教程详解
2019/07/01 Python
Python基于字典实现switch case函数调用
2020/07/22 Python
Python字符串函数strip()原理及用法详解
2020/07/23 Python
python中append函数用法讲解
2020/12/11 Python
如何用python开发Zeroc Ice应用
2021/01/29 Python
Python将QQ聊天记录生成词云的示例代码
2021/02/10 Python
html5 canvas实现跟随鼠标旋转的箭头
2016/03/11 HTML / CSS
HTML5新增的表单元素和属性实例解析
2014/07/07 HTML / CSS
创业女性典型材料
2014/05/02 职场文书
拾金不昧锦旗标语
2014/06/27 职场文书
同学毕业留言寄语
2015/02/27 职场文书
总经理助理岗位职责范本
2015/03/31 职场文书
2015年第十五个全民国防教育日宣传活动方案
2015/05/06 职场文书
初一年级组工作总结
2015/08/12 职场文书
Vue中插槽slot的使用方法与应用场景详析
2021/06/08 Vue.js
Python实现视频自动打码的示例代码
2022/04/08 Python
Java数组详细介绍及相关工具类
2022/04/14 Java/Android
JAVA springCloud项目搭建流程
2022/05/11 Java/Android