sql語句執行順序與效能優化(1)

Java散文詩發表於2018-10-14

一、首先我們看一下mysql的sql語句的書寫順序 。

select–distinct–from–on–where–group by–having–聚合函式cube、rollup–order by–limit–集合運算UNION,EXCEPT和INTERSECT

二、MySQL的語句執行順序,這個可以從官方文件檢視 ,也可以自己測試。

from -> on -> join -> where -> group by -> 聚集函式 cube|rollup -> having -> select -> 去重Distinct ->集合操作-> 排序order by -> 抽取分頁limit
MySQL的語句一共分為11步,如下圖所標註的那樣,最先執行的總是 FROM操作,最後執行的是LIMIT(條數)操作。其中每一個操作都會產生一張虛擬的表,這個虛擬的表作為一個處理的輸入,只是這些虛擬的表對使用者來說是透明 的,但是隻有最後一個虛擬的表才會被作為結果返回。如果沒有在語句中指定某一個子句,那麼將會跳過相應的步驟。

方法/步驟
下面我們來具體分析一下查詢處理的每一個階段
1. FROM: 對FROM的左邊的表和右邊的表計算笛卡爾積。產生虛表VT1
2. ON: 對虛表VT1進行ON篩選,只有那些符合的行才會被記錄在虛表VT2中。
3. JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那麼保留表中未匹配的行就會作為外部行新增到虛擬表VT2中,產生虛擬表VT3,
run from子句中包含兩個以上的表的話,那麼就會對上一個join連線產生的結果VT3和下一個表重複執行步驟1~3這三個步驟,一直到處理完所有的表為 止。
4. WHERE: 對虛擬表VT3進行WHERE條件過濾。只有符合的記錄才會被插入到虛擬表VT4中。
5. GROUP BY: 根據group by子句中的列,對VT4中的記錄進行分組操作,產生VT5.
6. CUBE | ROLLUP: 對錶VT5進行cube或者rollup操作,產生表VT6.
7. HAVING: 對虛擬表VT6應用having過濾,只有符合的記錄才會被 插入到虛擬表VT7中。
8. SELECT: 執行select操作,選擇指定的列,插入到虛擬表VT8中。
9. DISTINCT: 對VT8中的記錄進行去重。產生虛擬表VT9.
10. ORDER BY: 將虛擬表VT9中的記錄按照進行排序操作,產生虛擬表VT10.
11. LIMIT:取出指定行的記錄,產生虛擬表VT11, 並將結果返回。
END

三、簡要分析子句作用和執行方式,特意對應sql執行順序

可以充分考慮執行順序和執行方式和執行開銷,靈活調整sql,加快執行速度。布林表示式的位置可以直接用true和false加入測試驗證一下
from–where–group by–聚合函式–having–select–distinct–union all–order by–limit

from:資料來源,需要從哪個資料表檢索資料          從右向左,從下向上(←↑)
on:連線表進行過濾,布林表示式 。用逗號分隔的多個條件是 從右向左,從下向上(←↑),而單個布林表示式內部是從左向右,會觸發短路效果(比如先執行and和or的左側)。                                                              
join:資料來源,高開銷,按on條件保留驅動表未連線資料
where:過濾表中資料的條件,布林表示式,可以使用等號起到連線的作用 。 用逗號分隔的多個條件是 從右向左,從下向上(←↑),而單個布林表示式內部是從左向右,會觸發短路效果(比如先執行and和or的左側)。                           
group by:如何將上面過濾出的資料分組 ,通常將group by 的欄位放到select子句裡,從上到下,左到右(→↓)
cube,rollup:聚集函式,高開銷,聚合函式(統計用 sum,avg,max,min等)
having:對上面已經分組的資料進行過濾的條件 ,布林表示式,高開銷
select:獲取結果集,或列的計算結果 ,篩選結果列
distinct:針對欄位去除結果集重複行
union all,union,except,intersect :對結果集進行集合操作,差集,並集等,多個分句從左向右,從上到下,左到右(→↓),最左分句先開始。
order by:按欄位排序結果集。高開銷,多欄位從左向右從上向下執行 (→↓)
limit :和oracle的偽列 rownum對應執行位置,sqlserver的 top對應執行位置。都是最後執行的。在一個where子句裡rownum和top的位置不影響執行結果。截掉多餘的資料,保留剩餘結果集。
針對表和多個條件從右向左執行,針對結果集、欄位、布林表示式是從左向右執行。

 

四、sql子句的預設行為總結

 

  1.group by語句有預設的排序行為

  2.union 子句預設會去重排序

五、因為sql優化和很多因素相關 ,例如下面這些,我會在本系列逐項解析。

1.sql語句內的執行順序 和執行開銷
2.sql從執行到輸出的全生命週期
3.sql執行計劃
4.快取的存在和呼叫
5.表結構(schama),索引和檢視
6.資料量 和 資料儲存結構 
7.所用資料庫(schama)
8.資料庫執行引擎
9.cpu效能和記憶體佔用
10.磁碟IO和網路

2018-10-14

相關文章