- Hash Join (雜湊聯結):輸入兩資料表分為不同角色
- Build Input (建置輸入)
- 第一階段,較小的資料表
- 掃描或計算整個 "Build Input",依據 "間直資料行" 產生 "Hash Key" (雜湊鍵) 並建立 "Hash Table" (雜湊表),再依據 "Hash Key" (雜湊鍵) 將每個 "Row" (資料列) 置入 "Hash Bucket" (雜湊桶)
- Probe Input (探查輸入)
- 第二階段,較大的資料表
- 掃描或逐列計算整個 "Probe Input",針對每個 "探查輸入" 的資料列計算 "Hash Key" (雜湊鍵值),並掃描對應至 "Hash Bucket" (雜湊桶),並產生符合項目
- "Merge Join" 與 "Hash Join" 之間差異,什麼樣的情況適合使用 "Merge Join" 或 "Hash Join"
- 資料庫使用 Adventure Works for SQL Server 2012 的資料表 Sales.SalesOrderHeader 與 Sales.SalesOrderDetail 創建 3 個 table 如下
- tbSalesOrderHeader
- unique Clustered index:SalesOrderID
- tbSalesOrderDetail01
- tbSalesOrderDetail02
- unique Clustered index:SalesOrderID, SalesOrderDetailID
select *
from tbSalesOrderHeader o
join tbSalesOrderDetail01 od ON o.SalesOrderID = od.SalesOrderID
select *
from tbSalesOrderHeader o
join tbSalesOrderDetail02 od ON o.SalesOrderID = od.SalesOrderID
- 查詢結果
- 查詢 1:沒建立 "SalesOrderID" 為鍵值資料行的索引,因此採用 "Hash Join",若沒使用 "Hash Join" 將會增加 "排序" 作業,才能使用 "Merge Join",這樣成本更高
- 查詢 2:建立 "SalesOrderID" 為鍵值資料行的索引,而經過排序,所以採用 "Merge Join"
- 查詢 1 中 "tbSalesOrderHeader" 與 "tbSalesOrderDetail01" 屬於 "一對多" (或稱父子關係),因 "tbSalesOrderHeader" 資料列必定少於 "tbSalesOrderDetail01"
- 所以 "Hash Join" 中的 "Build Input" (建置輸入) 為 "tbSalesOrderHeader",可見 "tbSalesOrderHeader" 被置放於上面的位置
- Result:
- "Merge Join" 與 "Hash Join" 較適合大型的查詢,查詢資料較多的情況
- "Merge Join" 適合兩資料表都有 "索引" 或是經過事先排序過的情況
- 不適合 "Merge Join" 的情況下,將採用 "Hash Join"
- REF:
沒有留言:
張貼留言