JOIN 條件是否像連接表上的循環一樣工作?
條件是否
JOIN
像循環一樣工作?(likeForeach
)如果是這樣,它是在第一個表(一個 afterSELECT
)還是第二個表(一個 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次迭代
- 散列連接是一種更複雜的算法,計算量很大,但如果n和m很大會更快
n和m是從要連接的兩個表中估計的行數
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
在排序集之間查找匹配值非常容易,您可以直覺地完成。無需在整個其他集合中搜尋匹配項。
這種方法的優點是沒有隨機訪問。兩組都按順序掃描,並且只掃描一次,如果數據集很大,這很重要。
考慮以下情況:
你有一個大活頁夾,裡面有厚厚的一堆稅單,你只是按日期排序,你為自己感到驕傲。然後您會注意到另一堆您忘記插入的稅表。
最佳解決方案是以與活頁夾相同的順序對紙堆進行分類,然後按順序翻閱活頁夾和已分類的表格堆,將表格插入活頁夾的正確位置。那是手動合併連接。
使用索引的手動嵌套循環連接將是:對於每個新表單,找到它應該在活頁夾中的位置,然後將其放入。如果堆沒有排序,你必須在兩個方向上翻閱活頁夾很多更多,做隨機訪問,它會更慢。