概述
一條普通的SQL查詢語句它在MySQL數據庫中是怎么樣被解析和執行的呢?下面一起來了解一下,MySQL是如何解析SQL查詢語句的,這對理解MySQL的執行計劃也大有益處。
解析順序
下面是一條普通的SQL查詢語句偽代碼
SELECT DISTINCT
< select_list >
FROM
< left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
< where_condition >
GROUP BY
< group_by_list >
HAVING
< having_condition >
ORDER BY
< order_by_condition >
LIMIT < limit_number >
它的解析順序,實際上是下面這樣子的
1 FROM <left_table>
2 ON <join_condition>
3 <join_type> JOIN <right_table> 第2步和第3步會循環執行
4 WHERE <where_condition> 第4步會循環執行,多個條件的執行順序是從左往右的。
5 GROUP BY <group_by_list>
6 HAVING <having_condition>
7 SELECT 分組之后才會執行SELECT
8 DISTINCT <select_list>
9 ORDER BY <order_by_condition>
10 LIMIT <limit_number> 前9步都是SQL92標準語法。limit是MySQL的獨有語法。
MySQL是關系型數據庫,基于行和列的結構。SQL語句查詢,目的就是檢索數據庫中符合條件的數據行和列,反過來說就是把結果集中不符合條件的數據行和列過濾掉,然后返回符合條件的數據行和列。從整個角度出發,可以把一條SQL語句及其解析順序的構成歸納以下4個部分
- 行過濾
步驟1~6對數據行進行過濾
- 列過濾
步驟7~8對數據列進行過濾
- 排序
步驟9對數據結果進行排序
- 分頁
步驟10是MySQL特有的屬性,它對數據結果進行分頁
解析細節分析
- FROM
對FROM的左邊的表和右邊的表數據進行笛卡爾積(CROSS JOIN)運算,產生虛表VT1。產生的虛表VT1將傳遞給下一步驟進行運算。
- ON過濾
對虛表VT1進行ON篩選,符合條件的數據行被記錄在虛表VT2中。
- OUTER JOIN添加外部列
如果指定了 OUTER JOIN(比如LEFT JOIN、 RIGHT JOIN),【主表中未匹配的數據行】也會保留添加到虛擬表VT2 中,產生虛擬表VT3 。 如果FROM子句中包含兩個以上的表的話,那么就會對上一個JOIN連接產生的結果VT3和下一個表重復執行步驟1~3這三個步驟,一直到處理完所有的表為止。
- WHERE
對虛擬表VT3 進行WHERE條件過濾。只有符合的記錄才會被插入到虛擬表VT4中。
- GROUP BY
根據group by子句中的列,對VT4中的記錄進行分組操作,產生虛擬表VT5 。
- HAVING
對虛擬表VT5應用having過濾,符合的記錄會被插入到虛擬表VT6中。
- SELECT
這個子句對SELECT子句中的元素進行處理,生成VT7表。
- DISTINCT
尋找VT7中的重復列,并刪掉,生成VT8。如果在查詢中指定了DISTINCT子句,則會創建一張內存臨時表(如果內存放不下,就需要存放在硬盤了)。這張臨時表的表結構和上一步產生的虛擬表VT7是一樣的,不同的是對進行DISTINCT操作的列增加了一個唯一索引,以此來除重復數據。
- ORDER BY
從VT8中的表中,根據ORDER BY 子句的條件對結果進行排序,生成VT9表。
- LIMIT
LIMIT子句從上一步得到的 VT9虛擬表 中選出從指定位置開始的指定行數據。
總結
- 魚骨圖
網上有人將SQL解析順序用圖表表示,很像一條魚骨,也很形象
SQL語句解析順序
- 流程分析
每個步驟中,都會產生一個虛表記錄過濾后的數據結果集,然后將傳遞給下一步驟進行運算。
1. FROM(將最近的兩張表,進行笛卡爾積)---VT1
2. ON(將VT1按照它的條件進行過濾)---VT2
3. LEFT|RIGHT JOIN(保留主表的記錄)---VT3
4. WHERE(過濾VT3中的記錄)--VT4…VTn
5. GROUP BY(對VT4的記錄進行分組)---VT5
6. HAVING(對VT5中的記錄進行過濾)---VT6
7. SELECT(對VT6中的記錄,選取指定的列)--VT7
8. DISTINCT (尋找VT7中的重復列,并刪掉)--VT8
9. ORDER BY(對VT8的記錄進行排序)--VT9
10. LIMIT(對排序之后的值進行分頁)--MySQL特有的語法
- WHERE條件解析順序
MySQL :從左往右去執行WHERE條件的。
Oracle :從右往左去執行WHERE條件的。