接續上篇 Nested Loops Join,本文深入剖析 **Hash Join (散列聯接)** — 大資料集聯接的利器。透過抽象代價模型 (假設緩衝區僅 1 頁) 推導 I/O 代價,對比 Nested Loops、Index Lookup、Hash Join 三者優劣,並以 Oracle 實測驗證優化器選擇邏輯。
兩表聯接 T1(c1) ⋈ T2(d1),筆數皆 100 萬:
關鍵細節:雜湊衝突 (不同鍵值落同桶) 需 **精確比對** 確認;支援 **Grace Hash** (遞歸分割) 與 **Recursive Hash** (多層分割) 處理超大資料集。
| 方法 | 假設條件 | Build/外表 I/O | Probe/內表 I/O | 總計 | 相對比 (以 Hash=1) |
|---|---|---|---|---|---|
| Nested Loops (無索引) | 各 100萬筆, 100筆/頁 | 100萬 × (10000+1) | - | 10,001,000,000 | 25,000 |
| Nested Loops (有索引) | 索引高度 4 | 100萬 × (4+1) | - | 5,000,000 | 1,250 |
| 臨時索引 | 建索引 3頁/筆 + 查詢 | 4,000,000 + 5,000,000 | - | 9,000,000 | 2,250 |
| Hash Join | 雜湊桶 1頁/筆 | 100萬 × (1+1) = 2,000,000 | 100萬 × (1+1) = 2,000,000 | 4,000,000 | 1,000 |
結論:大表聯接無索引時,Hash Join 代價最低,甚至優於有索引的 Nested Loops。
CREATE TABLE t1(c1 INT, c2 INT);
CREATE TABLE t2(d1 INT, d2 INT);
-- 各插入 10,000 筆
CREATE INDEX it1c1 ON t1(c1);
EXPLAIN PLAN FOR SELECT c1, d1 FROM t1 INNER JOIN t2 ON c1 = d1;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-- 結果:
-- HASH JOIN (Cost=13)
-- TABLE ACCESS FULL T1
-- TABLE ACCESS FULL T2
-- 即使 t1(c1) 有索引,優化器仍選 Hash Join!
| 資料庫 | Hash Join 關鍵字 | 備註 |
|---|---|---|
| Oracle | HASH JOIN | 支援 Parallel Hash Join |
| SQL Server | Hash Match (Inner Join) | 查看 `Hash Match` 物理運算子 |
| PostgreSQL | Hash Join | `enable_hashjoin` 參數控制 |
| MySQL 8.0+ | Hash Join | 僅支援 Inner Join,`optimizer_switch` 控制 |
| 達夢 | HASH JOIN | 國產資料庫同標準術語 |
讀懂 Hash Join 代價模型與執行計畫,你就掌握了大資料量聯接優化的核心鑰匙。