SQL查詢執(zhí)行順序分析
前言
了解 SQL 查詢的執(zhí)行順序?qū)ξ覀兘鉀Q一些問題很有幫助,有時(shí)我們可能會(huì)疑惑為什么不能對(duì)分組的結(jié)果進(jìn)行篩選這樣類似的問題?之前一直不是理解這個(gè)問題,在了解了SQL 查詢的執(zhí)行順序之后這個(gè)問題也就迎刃而解。在我們對(duì) SQL 查詢語句進(jìn)行分析優(yōu)化時(shí),掌握?qǐng)?zhí)行順序也是有一定幫助的。
一、理論順序
上面是圖示 SQL 的執(zhí)行順序,下面用列表列出:
FROM
ON
JOIN
WHERE
GROUP BY
CUBE | ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
LIMIT
上面所列出的執(zhí)行順序能幫助我們解答一些問題:
為啥不能對(duì)窗口函數(shù)的執(zhí)行結(jié)果進(jìn)行過濾?
因?yàn)榇翱诤瘮?shù)在 SELECT 步驟執(zhí)行,而這步是在 WHERE 和 GROUP BY 之后
可以對(duì)分組的結(jié)果進(jìn)行篩選嗎?
不可以,因?yàn)?GROUP BY 在 WHERE 之后執(zhí)行
可以對(duì)分組后的結(jié)果進(jìn)行排序嗎?
可以,因?yàn)?ORDER BY 在 GROUP BY 之后。
二、代碼示例
學(xué)生表
成績(jī)
查詢語句
查詢來自天津且總成績(jī)高于70分,并且查詢他們的總成績(jī),查詢結(jié)果按成績(jī)降序排列
SELECT ss.student_id,sum(se.grade) as total,ss.city FROM students ss LEFT JOIN score se ON ss.student_id = se.student_id WHERE ss.city = "天津" GROUP BY ss.student_id HAVING sum(se.grade) > 70 ORDER BY total DESC LIMIT 10
查詢結(jié)果
三、分析 SQL 執(zhí)行過程
SQL 運(yùn)行的每個(gè)操作都會(huì)產(chǎn)生一張?zhí)摂M表,只不過這些虛擬表對(duì)用戶是透明的,只有最后一步生成的虛擬表才會(huì)返回給用戶。
第一步執(zhí)行的是對(duì) FROM 字句前后的兩張表 students 和 score 進(jìn)行笛卡爾積操作,生成虛擬表VT1。
應(yīng)用 ON 過濾器
在虛擬表 VT1 中執(zhí)行過濾操作,過濾條件為:ss.student_id = se.student_id ?
對(duì)于在 ON 過濾條件下的 NULL 值比較,此時(shí)的比較結(jié)果為 UNKNOWN,卻被視為 FALSE 來進(jìn)行處理,即兩個(gè) NULL 并不相同。但是在下面兩種情況下認(rèn)為兩個(gè) NULL 值的比較是相等的:
GROUP BY 子句把所有 NULL 值分到同一組
ORDER BY 子句中把所有 NULL 值排列在一起
在產(chǎn)生虛擬表 VT2 時(shí),會(huì)增加一個(gè)額外的列來表示 ON 過濾條件的返回值,返回值有 TRUE、FALSE、UNKNOWN。取出比較值為 TRUE 的記錄,產(chǎn)生虛擬表 VT2。
添加外部行
這一步只有在連接類型為 OUTER JOIN 時(shí)才發(fā)生,如 LEFT OUTER JOIN、RIGHT OUTERJOIN、FULL OUTER JOIN。雖然在大多數(shù)時(shí)候我們可以省略 OUTER 關(guān)鍵字,但 OUTER 代表的就是外部行。LEFT OUTER JOIN 把左表記為保留表,RIGHT OUTER JOIN 把右表記為保留表,F(xiàn)ULL OUTER JOIN 把左右表都記為保留表。添加外部行的工作就是在 VT2 表的基礎(chǔ)上添加保留表中被過濾條件過濾掉的數(shù)據(jù),非保留表中的數(shù)據(jù)被賦予 NULL 值,最后生成虛擬表 VT3
應(yīng)用 WHERE 過濾器
對(duì)上一步驟產(chǎn)生的虛擬表 VT3 進(jìn)行 WHERE 條件過濾,只有符合<where_condition>的記錄才會(huì)輸出到虛擬表 VT4 中
在當(dāng)前應(yīng)用 WHERE 過濾器時(shí),有兩種過濾是不被允許的:
由于數(shù)據(jù)還沒有分組,因此現(xiàn)在還不能在 WHERE 過濾器中使用 where_condition=MIN(col)這類對(duì)統(tǒng)計(jì)的過濾
由于沒有進(jìn)行列的選取操作,因此在 SELECT 中使用列的別名也是不被允許的,如 SELECT city as c from students WHERE c = '天津' 是不允許出現(xiàn)的
分組
在本步驟中根據(jù)指定的列對(duì)上個(gè)步驟中產(chǎn)生的虛擬表進(jìn)行分組,最后得到虛擬表 VT5
應(yīng)用 HAVING 過濾器
在該步驟中對(duì)于上一步產(chǎn)生的虛擬表應(yīng)用 HAVING 過濾器,HAVING 是對(duì)分組條件進(jìn)行過濾的篩選器。生成虛擬表VT6。
處理 SELECT 列表
在這一步中,將 SELECT 中指定的列從上一步產(chǎn)生的虛擬表中選出生成虛擬表 VT7。
應(yīng)用 ORDER BY 字句
根據(jù) ORDER BY 子句中指定的列對(duì)上一步輸出的虛擬表進(jìn)行排列,返回新的虛擬表 VT8。
注意:在 MySQL 數(shù)據(jù)庫中,NULL 值在升序過程中總是首先被選出,即 NULL 值在 ORDER BY 子句中被視為最小值
LIMIT 子句
在該步驟中應(yīng)用 LIMIT 子句,從上一步驟的虛擬表中選出從指定位置開始的指定行數(shù)據(jù)。對(duì)于沒有應(yīng)用 ORDER BY 的 LIMIT 子句,結(jié)果同樣可能是無序的,因此 LIMIT 子句通常和 ORDER BY 子句一起使用。
四、注意
上面所討論的順序皆為理論上的執(zhí)行順序,實(shí)際上數(shù)據(jù)庫引擎并不是通過連接、過濾和分組來運(yùn)行查詢,因?yàn)樗鼘?shí)現(xiàn)了一系列優(yōu)化來提升查詢速度(不影響最終的返回結(jié)果)。數(shù)據(jù)庫引擎可能會(huì)為了提高查詢的速度把一些過濾條件進(jìn)行提前,當(dāng)然前提是不會(huì)對(duì)返回的結(jié)果造成影響。
SELECT ss.student_id,sum(se.grade) as total,ss.city FROM students ss LEFT JOIN score se ON ss.student_id = se.student_id WHERE ss.city = "天津"
這個(gè) sql 學(xué)生城市是天津的只有三個(gè),如果在學(xué)生很多的情況下如果先做城市的篩選后再對(duì)兩張表做笛卡爾積可以很大程度的提升性能,并且也不會(huì)對(duì)返回的結(jié)果造成影響。這時(shí)實(shí)際上SQL的執(zhí)行順序可能就與理論上的執(zhí)行順序不一樣了。
參考資料 SQL queries don't start with SELECT
以上就是SQL查詢執(zhí)行順序分析的詳細(xì)內(nèi)容,更多關(guān)于SQL查詢執(zhí)行順序的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mysql注入中的outfile、dumpfile、load_file函數(shù)詳解
這篇文章主要介紹了Mysql注入中的outfile、dumpfile、load_file,需要的朋友可以參考下2018-05-05mysql如何處理varchar與nvarchar類型中的特殊字符
這篇文章主要介紹了mysql如何處理varchar與nvarchar類型中的特殊字符,需要的朋友可以參考下2014-12-12mysql 常用數(shù)據(jù)庫語句 小練習(xí)
一個(gè)mysql小練習(xí) 建表 查詢 修改表 增加字段 刪除字段2009-07-07MySQL服務(wù)啟動(dòng)與關(guān)閉如何操作圖文詳解
這篇文章主要為大家介紹了MySQL服務(wù)啟動(dòng)與關(guān)閉如何操作圖文詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2023-10-10Ubuntu 18.04下mysql 8.0 安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了Ubuntu 18.04下mysql 8.0 安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05MySQL中CONCAT()函數(shù)拼接出現(xiàn)NULL的問題解決
本文主要介紹了MySQL中CONCAT()函數(shù)拼接出現(xiàn)NULL的問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03