Sql-Server

JOIN 條件是否像連接表上的循環一樣工作?

  • September 6, 2022

條件是否JOIN像循環一樣工作?(like Foreach)如果是這樣,它是在第一個表(一個 after SELECT)還是第二個表(一個 afterJOIN子句)上執行循環?

假設您有以下查詢:

SELECT * FROM Customers JOIN Orders ON Customers.ID = Orders.CustomerID

我想知道的是,這個ON子句是不是對第二張表中的每條記錄逐條檢查條件,看哪一條滿足條件?

JOIN 是類似於乘法的數學運算符。執行乘法有幾種算法。你在學校學過的經典,但在電腦程式中一些更有趣的不同,以減少計算時間

在RDBMS中,SQL引擎內部編寫了很多算法來解決關係代數的基本運算…

在 MySQL 這樣的低端 RDBMS 中,只有一種算法,那就是嵌套循環(2019 年添加了雜湊連接)。在更專業的 RDBMS 中,您會發現 3 種算法:嵌套循環、散列和合併。在最高端的 RDBMS 中,您會發現更多算法(UNION 或 CONCATENATE 連接、圖形橫向…)或對這些主要算法的改進(自適應連接)。

RDBMS 引擎之所以使用多種算法,是因為每種算法在面對一些統計數據、資料結構和連接複雜度時都有自己的性能。如果連接是一個簡單的連接,只有來自兩個不同表的兩列相等,則可以使用三種技術……但是:

  • 嵌套循環需要n x m次迭代
  • 合併循環需要最大n + m次迭代
  • 散列連接是一種更複雜的算法,計算量很大,但如果nm很大會更快

nm是從要連接的兩個表中估計的行數

SELECT * FROM ta JOIN tb ON condition

給出與嵌套循環相同的結果:

for each row of ta
   for each row of tb
       if condition
           append the row to the resultset

…但對行的順序沒有任何保證。

事實上,將其視為嵌套循環是一種誤導,因為您最終會認為行將按特定順序排列(這是錯誤的)或未正確優化您的連接條件。

假設表包含:

ta.value
----
A
C
D
E
F
Z    

tb.value
----
B
C
E
X    

如果你在 ta.value=tb.value 上加入它們,並且數據庫支持它,它可以使用合併連接。這涉及對兩個表進行排序(或者如果可用,則使用索引,這很方便,因為它已經排序),並將它們並排(實際上)放置,如下所示:

ta          tb
----        ----
A           
           B
C           C       <- match
D           
E           E       <- match
F
           X
Z

在排序集之間查找匹配值非常容易,您可以直覺地完成。無需在整個其他集合中搜尋匹配項。

這種方法的優點是沒有隨機訪問。兩組都按順序掃描,並且只掃描一次,如果數據集很大,這很重要。

考慮以下情況:

你有一個大活頁夾,裡面有厚厚的一堆稅單,你只是按日期排序,你為自己感到驕傲。然後您會注意到另一堆您忘記插入的稅表。

最佳解決方案是以與活頁夾相同的順序對紙堆進行分類,然後按順序翻閱活頁夾和已分類的表格堆,將表格插入活頁夾的正確位置。那是手動合併連接。

使用索引的手動嵌套循環連接將是:對於每個新表單,找到它應該在活頁夾中的位置,然後將其放入。如果堆沒有排序,你必須在兩個方向上翻閱活頁夾很多更多,做隨機訪問,它會更慢。

引用自:https://dba.stackexchange.com/questions/316515