首先看一下示例語句java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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 >
|
然而它的執行順序是這樣的post
1
2
3
4
5
6
7
8
9
10
|
1
FROM <left_table>
2
ON <join_condition>
3
<join_type> JOIN <right_table> 第二步和第三步會循環執行
4
WHERE <where_condition> 第四步會循環執行,多個條件的執行順序是從左往右的。
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的獨有語法
|
來看一個例子優化
假設有表1和表2spa
table13d
table2code
一、fromblog
2個表聯合查詢獲得他們的笛卡爾積CROSS JOIN,產生 虛表VT1排序
二、ON過濾索引
對 虛表VT1 進行ON篩選,只有那些符合的行纔會被記錄在虛表VT2中。
注意:這裏由於語法限制,使用了'WHERE'代替,從中讀者也能夠感覺到二者之間微妙的關係;內存
3.OUTER JOIN添加外部列
若是指定了 OUTER JOIN(好比left join、 right join) ,那麼 保留表中未匹配的行 就會做爲外部行 添加 到 虛
擬表VT2 中,產生 虛擬表VT3 。
若是FROM子句中包含兩個以上的表的話,那麼就會對上一個join鏈接產生的結果VT3和下一個表重複執行步驟1~3
這三個步驟,一直處處理完全部的表爲止
4.WHERE
對 虛擬表VT3 進行WHERE條件過濾。只有符合的記錄纔會被插入到 虛擬表VT4 中。
5.GROUP BY
根據group by子句中的列,對VT4中的記錄進行分組操做,產生 虛擬表VT5 。
注意:
其後處理過程的語句,如SELECT,HAVING,所用到的列必須包含在GROUP BY中。對於沒有出現的,得用聚合函
數;
緣由:
GROUP BY改變了對錶的引用,將其轉換爲新的引用方式,可以對其進行下一級邏輯操做的列會減小;
6.HAVING
對 虛擬表VT5 應用having過濾,只有符合的記錄纔會被 插入到 虛擬表VT6 中。
7.SELECT
這個子句對SELECT子句中的元素進行處理,生成VT5表。
(5-J1)計算表達式 計算SELECT 子句中的表達式,生成VT5-J1
8.DISTINCT
尋找VT5-1中的重複列,並刪掉,生成VT5-J2
若是在查詢中指定了DISTINCT子句,則會建立一張內存臨時表(若是內存放不下,就須要存放在硬盤了)。這張
臨時表的表結構和上一步產生的虛擬表VT5是同樣的,不一樣的是對進行DISTINCT操做的列增長了一個惟一索引,以
此來除重複數據
9.ORDER BY
從 VT5-J2 中的表中,根據ORDER BY 子句的條件對結果進行排序,生成VT6表。
注意:
惟一可以使用SELECT中別名的地方
10.LIMIT(MySQL特有)
LIMIT子句從上一步獲得的 VT6虛擬表 中選出從指定位置開始的指定行數據
注意:
offset 和 rows 的正負帶來的影響;
當偏移量很大時效率是很低的,能夠這麼作:
採用子查詢的方式優化 ,在子查詢裏先從索引獲取到最大id,而後倒序排,再取N行結果集
採用INNER JOIN優化 ,JOIN子句裏也優先從索引獲取ID列表,而後直接關聯查詢得到最終結果
解析順序總結
流程分析
1
2
3
4
5
6
7
8
9
|
1
. FROM(將最近的兩張表,進行笛卡爾積)---VT1
2
. ON(將VT1按照它的條件進行過濾)---VT2
3
. LEFT JOIN(保留左表的記錄)---VT3
4
. WHERE(過濾VT3中的記錄)--VT4…VTn
5
. GROUP BY(對VT4的記錄進行分組)---VT5
6
. HAVING(對VT5中的記錄進行過濾)---VT6
7
. SELECT(對VT6中的記錄,選取指定的列)--VT7
8
. ORDER BY(對VT7的記錄進行排序)--VT8
9
. LIMIT(對排序以後的值進行分頁)--MySQL特有的語法
|
流程說明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
單表查詢:根據 WHERE 條件過濾表中的記錄,造成中間表(這個中間表對用戶是不可見的);而後根據
SELECT 的選擇列選擇相應的列進行返回最終結果。
兩錶鏈接查詢:對兩表求積(笛卡爾積)並用 ON 條件和鏈接鏈接類型進行過濾造成中間表;而後根據
WHERE條件過濾中間表的記錄,並根據 SELECT 指定的列返回查詢結果。
笛卡爾積:行相乘、列相加
多表鏈接查詢:先對第一個和第二個表按照兩錶鏈接作查詢,而後用查詢結果和第三個表作鏈接查詢,以此
類推,直到全部的表都鏈接上爲止,最終造成一箇中間的結果表,而後根據WHERE條件過濾中間表的記錄,
並根據SELECT指定的列返回查詢結果。
|