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。