首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 聯結演算法 I/O 成本深度解析:Nested Loop vs Sort-Merge vs Hash Join

     編輯:關於SqlServer

三大聯結演算法與 I/O 成本模型

假設外部輸入關係 R (M 頁)、內部關係 S (N 頁),每頁可容納多筆資料。CPU 成本相對較小,重點在 **磁碟 I/O (頁面讀取次數)**。

1. Nested Loop Join (巢狀迴圈聯結)

邏輯:對 R 每列,掃描 S 全表 (或索引 Seek) 尋找匹配。

偽代碼:

for each r in R:
    for each s in S:
        if r.key == s.key: output(r,s)

I/O 成本 (Page-at-a-time 假設):

`Cost = M + M × N` (最壞:無索引、全表掃描 S)

  • 讀取 R:M 次 I/O
  • 對 R 每列,讀取 S:M × N 次 I/O

優化關鍵:

  • **小表做外層 (驅動表)**:M 越小越好。
  • **內層有索引**:`Cost ≈ M + M × (Index Depth + Matching Pages)`,大幅降低。
  • **適用場景**:外層極小 (< 100 列)、內層有高選擇性索引、或記憶體足夠容納內層 (緩存命中)。

2. Sort-Merge Join (排序合併聯結)

邏輯:兩輸入分別按聯結鍵排序 → 雙指標合併掃描 (類似合併排序合併步驟)。

步驟:

  1. Sort R on Join Key
  2. Sort S on Join Key
  3. Merge Scan:同步游標比對,輸出匹配列 (處理重複值需「分區」邏輯)

I/O 成本:

  • **最佳**:兩輸入**已排序** (叢集索引/覆蓋索引順序滿足) 且**至少一方無重複值** → `Cost = M + N` (單次掃描)。
  • **最差**:兩輸入**未排序** 且**全為重複值** → `Cost = M log M + N log N + M × N` (兩次外部排序 + 笛卡兒積)。

適用場景:大表聯大表、聯結鍵有叢集索引、或已預排序 (如 `ORDER BY` 相同)。

3. Hash Join (雜湊聯結) — 現代 OLAP 主流

邏輯**:

  1. Build Phase:掃描較小輸入 (Build Input),在記憶體建立雜湊表 (Bucket → 鏈表)。
  2. Probe Phase:掃描較大輸入 (Probe Input),計算雜湊值探測雜湊表,輸出匹配。
  3. 若記憶體不足,**Grace Hash Join**:將 Build/Probe 依雜湊值分割寫入 TempDB (Partition),再遞迴處理各分區。

I/O 成本**:

  • **記憶體足夠**:`Cost = M + N` (各掃描一次,零 TempDB I/O)。
  • **記憶體不足 (Grace)**:`Cost = 2×(M+N) + 2×(M+N) + ...` (多輪分割/讀寫 TempDB)。

適用場景**:大表聯大表、無合適索引、並行查詢、資料倉庫/OLAP 負載。

成本比較總結表

演算法最佳 I/O最差 I/O記憶體敏感度平行化典型適用
Nested LoopM + M×IndexSeekM + M×N低差 (單執行緒)小表驅動大表、索引 Seek
Sort-MergeM + N (已排序)M log M + N log N + M×N中 (排序需記憶體)好 (並行排序)大表聯大表、已排序輸入
Hash JoinM + N (記憶體足)多輪 TempDB 讀寫高 (需足夠記憶體避免分割)極好 (並行 Build/Probe)大表聯大表、無索引、OLAP

優化器選擇邏輯與干預

  • **統計資料準確** 是前提:`UPDATE STATISTICS WITH FULLSCAN`。
  • **強制指定**:`OPTION (LOOP JOIN | MERGE JOIN | HASH JOIN)` — 僅限測試/極特殊情況。
  • **記憶體授予**:`MAX_GRANT_PERCENT`、`MIN_GRANT_PERCENT` (SQL 2012+)、Resource Governor 控制 Hash/Sort 記憶體。
  • **避免隱式轉換、函數包裹聯結鍵** → 導致統計失效、優化器誤判基數 → 選錯演算法。

結語

理解三大聯結演算法的 I/O 成本曲線,能讓你從「看執行計畫」進階到「預測與干預優化器」。核心永遠是:**準確統計 + 合適索引 + 足夠記憶體 = Hash Join 稱霸大表聯結;小表驅動 + 索引 Seek = Nested Loop 稱霸 OLTP。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved