Mysql-Explain(三):输出列-id

简介

在上一篇文章中,我们准备好了演示的表和数据,下面就来开始介绍第一个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。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章