SQL Server支援的連線查詢實現演算法

2021-07-03 00:18:07 字數 3366 閱讀 1654

連線

sql server支援三種物理連線運算子:巢狀迴圈連線、合併連線及雜湊連線。在bookmark lookup示例中,已經接觸了巢狀迴圈連線。沒有最好的連線運算子,而且沒有連線運算子好或不好。每乙個連線運算子在正確的環境都會執行的很好,在錯誤的環境都會執行的不好。

巢狀迴圈連線

巢狀迴圈連線是最簡單和最基礎的連線方式。它對乙個表(外表)的每行和另外乙個表(稱為內行)的每行比較,尋找滿足謂詞連線的行。這裡的「內錶」和「外表」指的是連線的輸入。「內連線」和「外連線」指的是邏輯上連線操作符的語義。可以用偽**表示巢狀迴圈連線的演算法。

for each row r1 in the outer table

for each row r2 in the inter table

if r1 joins with r2

return (r1, r2)

所有的行都會進行比較,導致這個演算法的消耗與外表、內錶乘機的大小成比例。因為消耗隨著內錶大小的增加而變得更大,在實踐中優化器試著通過減少對於每個外表必須處理的內錶行數來減少消耗。

例如,考慮下面的查詢:

select o.[orderid] 

from [customers] c join [orders] o on c.[customerid] = o.[customerid]

where c.[city] = 'london'

當執行此查詢時,使用下面的查詢計畫:

在這個計畫中外表是客戶,內錶是訂單。因此,對於巢狀迴圈連線符,sql server從客戶表開始尋找。連線每一次提取乙個客戶,對於每個客戶,在order表中執行一次索引。因為這裡有6個客戶,它在order表中執行6次索引查詢。注意在order表中的索引查詢依賴與客戶表中的客戶id。6次中的每一次,sql server重複在order表中查詢索引,客戶id有不同的值。因此,6次索引查詢執行的每次結果不同,也返回不同的行。

把客戶id稱作關聯引數。如果巢狀迴圈連線包含有關聯引數,則在查詢計畫中以outer referenes表示。經常把巢狀迴圈連線這種有依賴與關聯引數的索引查詢稱作索引連線。索引連線是巢狀迴圈連線中最常見的型別。

上乙個例子說明了sql server對巢狀迴圈連線提高效能的兩個重要技術:關聯引數和乙個在連線內部中基於關聯引數的索引查詢。另乙個沒有提高的效能優化的方法是在連線內部使用儲存池。乙個儲存池能夠從連線內部快取和重新訪問結果。儲存池在有很多重複值的關聯引數和在連線內部估計會有很大消耗時有用。通過使用儲存池,sql server可以避免對相同關聯引數的連線內部重新計算多次。

不是所有巢狀迴圈連線都有關聯引數。得到乙個沒有關聯引數的簡單方法是交叉連線,交叉連線把乙個表中所有的行和另一外表中所有的行結合起來。為了用巢狀迴圈連線實現乙個交叉連線,必須搜尋和連線內錶和外表的每行。內錶行的集合不會依賴外表處理的行而改變。因此,對於交叉連線,沒有關聯引數。

如果沒有合適的索引或適合索引查詢的謂詞連線,優化器可以使用乙個沒有連線引數的查詢計畫。對於決定乙個謂詞連線是否適合使用乙個索引查詢的規則,是和決定另外謂詞是否適合索引查詢一樣的。例如:通過以下查詢可以查到返回僱傭的員工數:

select e1.[employeeid], count(*)

from [employees] e1 join [employees] e2

on e1.[hiredate] 

group by e1.[employeeid]

在僱傭日期列中沒有索引,因此,這個查詢產生乙個有謂詞,但是沒有關聯引數和索引查詢的簡單巢狀迴圈連線:

合併連線

合併連線不支援任何連線謂詞的巢狀迴圈連線,合併連線至少需要乙個等值連線謂詞。而且,合併連線的輸入必須儲存在聯結器上。例如,如果有乙個連線謂詞[customers].[customerid] = [orders].[customerid] ,客戶id都必須儲存在客戶的id列中。

合併連線也是在讀的同時對兩個儲存輸入的一行進行比較。在每個步驟中,比較每個輸入的下一行。如果兩行是相同,輸出乙個連線後的行並繼續。如果行是不同的,捨棄兩個輸入行中較少的那個並繼續。因為輸入是儲存,連線捨棄的任何行必須比兩個輸入中任何剩下的行要小,因此可以永不連線。合併連線不需要對兩個輸入中的每一行掃瞄。只要到了兩個輸入中的某乙個的末尾,合併連線就會停止掃瞄。

巢狀迴圈連線總的消耗和在輸入表中行的乘積成比例,不同於巢狀迴圈連線,合併連線的表最多讀一次,總的消耗和輸入行數的總數成正比例,因此何必連線對於大量的輸入是較好的選擇。

排序合併連線和索引合併連線

對於乙個合併連線,sql server有兩種方法得到排序的輸入;直接使用排序操作符對輸入排序,或者可能從乙個索引中讀行。一般來說,乙個通過使用索引獲得排序次序的計畫比直接使用排序的消耗要少。

連線謂詞和邏輯連線型別

合併連線支援多等值連線謂詞,只要在所有連線鍵上輸入是排序的。只要二者的輸入有著一樣的排序,特定排序次序就是不匹配。例如,如果有乙個連線謂詞t1.[col1] = t2.[col1] and t1.[col2] = t2.[col2],只要表t1和表t2在(col1,col2)上都一樣排序,就可以使用合併連線。

雜湊連線

雜湊連線是第二個物理連線操作符。當提到物理連線操作符時,雜湊連線是乙個重要的部分。巢狀迴圈連線對於小的資料集很有用,雜湊連線對於大型資料集很有用。雜湊連線在並行性和比例行方面優於其他連線,並且對於資料倉儲的查詢請求反映很快。跟合併連線一樣,雜湊連線至少需要乙個等值連線謂詞,支援剩餘謂詞。不同於合併連線,雜湊連線不需要排序的輸入集。

雜湊連線在執行時分成兩個階段,即構建階段和探索階段。在構建階段,雜湊連線從乙個輸入(通常稱之為左輸入或構建輸入)中讀入所有的行,對等值連線鍵上的列雜湊,然後建立或構建乙個記憶體雜湊表。在探索階段,雜湊連線從第二個輸入(通常稱之為右輸入)中讀入所有的行,在相同的等值連線鍵上對行雜湊,然後在雜湊表中查詢或探索匹配的行。由於雜湊函式可能導致衝突,雜湊連線必須對潛在的匹配進行檢查來確定已連線。

注意,不同於輸入行立即開始的巢狀迴圈連線和合併連線,雜湊連線在構建輸入時被阻塞。也就是說,雜湊連線必須讀入和處理所有的構建輸入,之後才能返回行。不同於其他連線方法,雜湊連線需要乙個記憶體區域儲存雜湊表。因此,sql server在任何時候,對於併發的雜湊連線資料有限制。這些特性和約束通常對於資料倉儲不是什麼問題,但是他們可能為大多數聯機事務處理帶來不必要的麻煩。

C 連線SQL server 增 刪 改 查

using system using system.collections.generic using system.data.sqlclient using system.linq using system.text using system.threading.tasks namespace 0...

php支援連線sqlserver資料庫

1 軟體配置 win7 64 wampserver2.2d x32 sql server 2008 r2資料庫,wamp2.2中的php版本是5.3.10。php環境也可以換成php apache。2 支援連線mysql server配置 php版本5.3以前,有php mssql功能,可以使用,但...

jdbc連線Sql server資料庫,並查詢資料

string driver com.microsoft.sqlserver.jdbc.sqlserverdriver string url jdbc sqlserver string user sa string password 123456 connection con null prepare...