SQL 查詢的執行順序

来源:https://www.cnblogs.com/emanjusaka/archive/2023/09/04/page_6.html
-Advertisement-
Play Games

瞭解 SQL 查詢的執行順序對我們解決一些問題很有幫助,有時我們可能會疑惑為什麼不能對分組的結果進行篩選這樣類似的問題?之前一直不是理解這個問題,在瞭解了SQL 查詢的執行順序之後這個問題也就迎刃而解。在我們對 SQL 查詢語句進行分析優化時,掌握執行順序也是有一定幫助的。 ...


by emanjusaka from ​ https://www.emanjusaka.top/archives/6 彼岸花開可奈何
本文歡迎分享與聚合,全文轉載請留下原文地址。

前言

瞭解 SQL 查詢的執行順序對我們解決一些問題很有幫助,有時我們可能會疑惑為什麼不能對分組的結果進行篩選這樣類似的問題?之前一直不是理解這個問題,在瞭解了SQL 查詢的執行順序之後這個問題也就迎刃而解。在我們對 SQL 查詢語句進行分析優化時,掌握執行順序也是有一定幫助的。

一、理論順序

SQL 執行順序

上面是圖示 SQL 的執行順序,下麵用列表列出:

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. CUBE | ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. LIMIT

上面所列出的執行順序能幫助我們解答一些問題:

  • 為啥不能對視窗函數的執行結果進行過濾?

    因為視窗函數在 SELECT 步驟執行,而這步是在 WHERE 和 GROUP BY 之後

  • 可以對分組的結果進行篩選嗎?

    不可以,因為 GROUP BY 在 WHERE 之後執行

  • 可以對分組後的結果進行排序嗎?

    可以,因為 ORDER BY 在 GROUP BY 之後。

二、代碼示例

  • 學生表

    image

  • 成績表

    image

  • 查詢語句

    查詢來自天津且總成績高於70分,並且查詢他們的總成績,查詢結果按成績降序排列

    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
    
  • 查詢結果

    image

三、分析 SQL 執行過程

SQL 運行的每個操作都會產生一張虛擬表,只不過這些虛擬表對用戶是透明的,只有最後一步生成的虛擬表才會返回給用戶。

  1. 第一步執行的是對 FROM 字句前後的兩張表 students 和 score 進行笛卡爾積操作,生成虛擬表VT1。

  2. 應用 ON 過濾器

    在虛擬表 VT1 中執行過濾操作,過濾條件為:ss.student_id = se.student_id ​

    對於在 ON 過濾條件下的 NULL 值比較,此時的比較結果為 UNKNOWN,卻被視為 FALSE 來進行處理,即兩個 NULL 並不相同。但是在下麵兩種情況下認為兩個 NULL 值的比較是相等的:

    • GROUP BY 子句把所有 NULL 值分到同一組
    • ORDER BY 子句中把所有 NULL 值排列在一起

    在產生虛擬表 VT2 時,會增加一個額外的列來表示 ON 過濾條件的返回值,返回值有 TRUE、FALSE、UNKNOWN。取出比較值為 TRUE 的記錄,產生虛擬表 VT2。

  3. 添加外部行

    這一步只有在連接類型為 OUTER JOIN 時才發生,如 LEFT OUTER JOIN、RIGHT OUTERJOIN、FULL OUTER JOIN。雖然在大多數時候我們可以省略 OUTER 關鍵字,但 OUTER 代表的就是外部行。LEFT OUTER JOIN 把左表記為保留表,RIGHT OUTER JOIN 把右表記為保留表,FULL OUTER JOIN 把左右表都記為保留表。添加外部行的工作就是在 VT2 表的基礎上添加保留表中被過濾條件過濾掉的數據,非保留表中的數據被賦予 NULL 值,最後生成虛擬表 VT3

  4. 應用 WHERE 過濾器

    對上一步驟產生的虛擬表 VT3 進行 WHERE 條件過濾,只有符合<where_condition>的記錄才會輸出到虛擬表 VT4 中

    在當前應用 WHERE 過濾器時,有兩種過濾是不被允許的:

    • 由於數據還沒有分組,因此現在還不能在 WHERE 過濾器中使用 where_condition=MIN(col)這類對統計的過濾
    • 由於沒有進行列的選取操作,因此在 SELECT 中使用列的別名也是不被允許的,如 SELECT city as c from students WHERE c = '天津' 是不允許出現的
  5. 分組

    在本步驟中根據指定的列對上個步驟中產生的虛擬表進行分組,最後得到虛擬表 VT5

  6. 應用 HAVING 過濾器

    在該步驟中對於上一步產生的虛擬表應用 HAVING 過濾器,HAVING 是對分組條件進行過濾的篩選器。生成虛擬表VT6。

  7. 處理 SELECT 列表

    在這一步中,將 SELECT 中指定的列從上一步產生的虛擬表中選出生成虛擬表 VT7。

  8. 應用 ORDER BY 字句

    根據 ORDER BY 子句中指定的列對上一步輸出的虛擬表進行排列,返回新的虛擬表 VT8。

    註意:在 MySQL 資料庫中,NULL 值在升序過程中總是首先被選出,即 NULL 值在 ORDER BY 子句中被視為最小值

  9. LIMIT 子句

    在該步驟中應用 LIMIT 子句,從上一步驟的虛擬表中選出從指定位置開始的指定行數據。對於沒有應用 ORDER BY 的 LIMIT 子句,結果同樣可能是無序的,因此 LIMIT 子句通常和 ORDER BY 子句一起使用。

四、註意

上面所討論的順序皆為理論上的執行順序,實際上資料庫引擎並不是通過連接、過濾和分組來運行查詢,因為它實現了一系列優化來提升查詢速度(不影響最終的返回結果)。資料庫引擎可能會為了提高查詢的速度把一些過濾條件進行提前,當然前提是不會對返回的結果造成影響。

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 = "天津"

這個 sql 學生城市是天津的只有三個,如果在學生很多的情況下如果先做城市的篩選後再對兩張表做笛卡爾積可以很大程度的提升性能,並且也不會對返回的結果造成影響。這時實際上SQL的執行順序可能就與理論上的執行順序不一樣了。

參考資料

  1. SQL queries don't start with SELECT

本文原創,才疏學淺,如有紕漏,歡迎指正。尊貴的朋友,如果本文對您有所幫助,歡迎點贊,並期待您的反饋,以便於不斷優化。

原文地址: https://www.emanjusaka.top/archives/6

微信公眾號:emanjusaka的編程棧


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ![](https://img2023.cnblogs.com/blog/3076680/202309/3076680-20230904164459431-1322523641.png) # 1. 儘管SQL標準指定了部分函數,但資料庫廠商並沒有遵循這些函數規範 # 2. 字元串 ## 2.1. c ...
  • 1. SQL語句類型 1. DDL(Data Definition Language,數據定義語言): DDL語句用於定義資料庫對象(如表、索引、視圖等)。常見的DDL語句包括: CREATE:用於創建資料庫對象,如創建表、索引、視圖等。 ALTER:用於修改資料庫對象的結構,如修改表的列、添加約束 ...
  • Redis OSS的邏輯資料庫,無論是自部署還是作為ElastiCache等托管服務啟動,其目的都是通過減少管理需求並提供一系列的預設設置來簡化開發人員的工作。然而,在實際生產中,當您的功能和操作需求發生變化時,單個Redis實例可能不再足夠。 ...
  • 如今隨著互聯網技術快速發展,業務越來越複雜,系統的高併發和關鍵數據的場景越來越多。在分散式系統中,機器宕機和消息丟失也是需要重點關註的問題,其中的一個典型就是冪等性問題。 ...
  • 伺服器顯卡在高性能計算和人工智慧應用中扮演著至關重要的角色。高性能計算廣泛應用於科學計算、工程設計、氣象預測等領域,而人工智慧應用則涵蓋了機器學習、深度學習、圖像識別等領域。這些應用需要大量的計算資源和高效的演算法來處理大規模的數據集,而伺服器顯卡正是在這樣的應用中發揮重要作用。 ...
  • 為解決用戶面臨的 MongoDB 遷移問題,玖章算術旗下的雲原生智能數據管理平臺 NineData 推出了 MongoDB 業務不停服數據遷移能力。NineData 實現了完全自動化的全量數據遷移,以及增量數據的採集複製能力。 ...
  • 本文簡單介紹了讀寫分離架構,和出現主從延遲後,如果我們用的讀寫分離的架構,那麼我們應該怎麼處理這種情況,相信在日常我們的主從還是或多或少的存在延遲。上面介紹的幾種方案,有些方案看上去十分不靠譜,有些方案做了一些妥協,但是都有實際的應用場景,需要我們根據自身的業務情況,合理選擇對應的方案。 ...
  • 本文分享自華為雲社區《直播回顧 | 數倉資源管控理論已掌握,是時候實戰了》,作者:胡辣湯 。 混合負載場景下,如何高效運維資料庫,防止資料庫系統過載?GaussDB(DWS)資源管控為資料庫平穩可靠運行提供了哪些助力?本期《數倉專家手把手教您資源管控與運維實戰》的主題直播中,我們邀請到華為雲Gaus ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...