Mysql-Explain(三):输出列-id
Mysql-Explain(一):explain简介和输出列解释
Mysql-Explain(二):explain实验数据准备
Mysql-Explain(三):输出列-id
Mysql-Explain(四):输出列-select_type
Mysql-Explain(五):输出列-type
Mysql-Explain(六):输出列-possiable_keys、key、key_len
Mysql-Explain(七):输出列-ref、rows
Mysql-Explain(八):输出列-extra
简介
在上一篇文章中,我们准备好了演示的表和数据,下面就来开始介绍第一个explain输出列:id.
字段 | 字段说明 | 字段值描述 | |
---|---|---|---|
id | select查询序列号,包含一组数字,表示查询中执行select子句或者操作表的顺序 | id相同 | 执行顺序由上至下 |
id不相同 | 如果是子查询,id的序号会递增,id的值越大被执行的优先级越高 | ||
id相同和不相同都存在 | 如果id相同可以认为是一组,同一组id执行顺序由上至下,不同组之间,id值越大被执行的优先级越高 |
演示
-
id相同:执行顺序由上至下
mysql> explain select * from student,school,major -> where student.school_id = school.id and student.major_id = major.id -> and student.major_id = 321 limit 10; +----+-------------+---------+------------+--------+---------------+---------+---------+------------------------+---------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+--------+---------------+---------+---------+------------------------+---------+----------+-------------+ | 1 | SIMPLE | major | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL | | 1 | SIMPLE | student | NULL | ALL | NULL | NULL | NULL | NULL | 1994898 | 10.00 | Using where | | 1 | SIMPLE | school | NULL | eq_ref | PRIMARY | PRIMARY | 4 | mydb.student.school_id | 1 | 100.00 | NULL | +----+-------------+---------+------------+--------+---------------+---------+---------+------------------------+---------+----------+-------------+ 3 rows in set, 1 warning (0.00 sec)
Id列的结果值全部是1,表示由上到下,先查询major表,刷选出major.id=321的记录,然后再查询student表,最后查询school表,这是MySQL优化器分析查询语句后得出的查询顺序。
-
id不同:如果是子查询,id的序号会递增,id的值越大被执行的优先级越高
mysql> explain -> select * from student -> where student.school_id = (select id from school where id < 2) limit 10; +----+-------------+---------+------------+-------+---------------+---------+---------+------+---------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+-------+---------------+---------+---------+------+---------+----------+--------------------------+ | 1 | PRIMARY | student | NULL | ALL | NULL | NULL | NULL | NULL | 1994898 | 10.00 | Using where | | 2 | SUBQUERY | school | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 1 | 100.00 | Using where; Using index | +----+-------------+---------+------------+-------+---------------+---------+---------+------+---------+----------+--------------------------+ 2 rows in set, 1 warning (0.00 sec)
上图所示,id分别是1和2,2>1,表示子查询将优先被执行,之后再执行主查询,这个应该非常直观也非常容易理解。
-
id同时存在相同和不相同:id相同为同一组,组内执行顺序由上至下,组间id值越大被执行的优先级越高
mysql> explain -> select student.*,sc.name from -> (select * from school where school.id < 10 limit 2)sc,student -> where sc.id = student.school_id; +----+-------------+------------+------------+-------+---------------+---------+---------+------+---------+----------+----------------------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+------------+------------+-------+---------------+---------+---------+------+---------+----------+----------------------------------------------------+ | 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | NULL | | 1 | PRIMARY | student | NULL | ALL | NULL | NULL | NULL | NULL | 1994898 | 10.00 | Using where; Using join buffer (Block Nested Loop) | | 2 | DERIVED | school | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 100.00 | Using where | +----+-------------+------------+------------+-------+---------------+---------+---------+------+---------+----------+----------------------------------------------------+ 3 rows in set, 1 warning (0.00 sec)
上图所示id分别是1、1、2,表示查询被分成了两组,组2优先被查询,也就是对表school的子查询优先被执行了,然后再执行到组1。组1内的执行顺序由上至下,先执行对表<derived2>的查询,再执行对表student的查询。
tips:
- <derived2>是派生表2的意思,后面select_type会讲到。
- form子查询语句中加LIMIT 2的原因是在MYSQL 5.7后,引入了derived_merge,一种查询优化技术,作用就是把派生表合并到外部的查询中,提高数据检索的效率。举例来说:“select * from (select * from a) aa where aa.id =1;”,在derived_merge下会被优化成"select * from a where a.id =1;",但是当派生子查询存在以下操作时该特性无法生效:UNION 、GROUP BY、DISTINCT、LIMIT/OFFSET以及聚合操作。由于上面做实验的例子比较简单在derived_merge打开的情况下from子查询会合并到外层查询,无法演示效果,因此在子查询语句中加了limit,当然也可以通过设置属性"optimizer_switch='derived_merge=off"来关闭derived_merge。