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。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章