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为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)
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值越大被执行的优先级越高。

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)

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

包含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

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)

第二个或更靠后的 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)

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

| UNION RESULTunion_resultResult of a UNION.
| SUBQUERYNoneFirst SELECT in subquery
| DEPENDENT SUBQUERYdependent (true)First SELECT in subquery, dependent on outer query
| DERIVEDNoneDerived table
| MATERIALIZEDmaterialized_from_subqueryMaterialized subquery
| UNCACHEABLE SUBQUERYcacheable (false)A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query
| UNCACHEABLE UNIONcacheable (false)The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)

总结

更多相关文章

  1. MySQL系列多表连接查询92及99语法示例详解教程
  2. Linux下MYSQL 5.7 找回root密码的问题(亲测可用)
  3. MySQL 什么时候使用INNER JOIN 或 LEFT JOIN
  4. Pycharm安装PyQt5的详细教程
  5. android 分辨率及密度详细
  6. android 分辨率及密度详细
  7. android从服务器下载文件(php+apache+win7+MySql)
  8. 四.Android六种布局详细讲解
  9. android 百度地图SDK 获得详细路线信息

随机推荐

  1. Android选择一段日期
  2. Migrate to Android Plugin for Gradle 3
  3. Bugly捕获异常(Android)
  4. Android 之 资源自适应与国际化
  5. Android 图片加载缓存
  6. ProgressBar 样式
  7. Android 存储用户信息
  8. Android入门基础:从这里开始
  9. android 监听联系人数据库
  10. android CoordinatorLayout 使用