MySQL的sql解析

首先看一下示例語句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指定的列返回查詢結果。
相關文章
相關標籤/搜索