欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SQL查詢執(zhí)行順序分析

 更新時(shí)間:2023年09月13日 11:01:55   作者:emanjusaka  
這篇文章主要為大家介紹了SQL查詢執(zhí)行順序分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

了解 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)文章

最新評(píng)論