'123')。WHERE col1='123' OR col2='123' OR ... vs UNION ALL 多條 SELECT 串接。| 資料量 | 查詢模式 | 3 欄位 | 5 欄位 |
|---|---|---|---|
| 10 萬 | OR | 4 秒 | 4 秒 |
| 10 萬 | UNION ALL | 11 秒 | 19 秒 |
| 100 萬 | OR | 37 秒 | 38 秒 |
| 100 萬 | UNION ALL | 1 分 53 秒 | 2 分 24 秒 |
| 1000 萬 | OR | 急劇增長 (文中未給具體值,趨勢同 100 萬) | 急劇增長 |
| 1000 萬 | UNION ALL | 更慘烈 | 更慘烈 |
OR 讓優化器產生 **單一 Clustered Index Scan/Table Scan**,一遍讀完所有頁面,在記憶體中評估所有 OR 條件。SELECT 獨立掃描整張表。3 條 UNION ALL = 掃 3 次表;5 條 = 掃 5 次。I/O 成倍增長。WHERE col1=@v 用 IX_col1,WHERE col2=@v 用 IX_col2。OR 往往導致**索引合併失效** 或轉全掃,而 UNION ALL 能精準走各自索引求並集。UNION (非 ALL) 自動去重,但需排序/雜湊成本高。UNION ALL 配合 ORDER BY ... OFFSET ... FETCH 可避免全量排序。ALTER TABLE BigTable ADD SearchKey AS (ISNULL(col1,'') + '|' + ISNULL(col2,'') + '|' + ISNULL(col3,''));
CREATE INDEX IX_SearchKey ON BigTable(SearchKey);
-- 查詢: WHERE SearchKey LIKE '%|123|%' -- 仍需掃描,但可配合全文檢索
CONTAINS((col1,col2,col3), '123') 反向索引極快。IF EXISTS (SELECT 1 FROM sys.indexes WHERE name='IX_col1' AND object_id=OBJECT_ID('BigTable'))
-- 有索引走 UNION ALL 動態拼接
ELSE
-- 無索引走單一 OR 查詢
若在 col1, col2, col3 各建非叢集索引:
OR:優化器常選 **Index Union** (多索引掃描 + Merge Join) 或直接 **Clustered Scan** (若估算回表成本高)。UNION ALL:各 SELECT 精準 **Index Seek + Key Lookup**,總成本 = Σ(索引範圍掃描 + 回表)。OR (或 IN),單次 I/O 最省。UNION ALL 讓每個條件獨立走索引,避免優化器放棄索引。UNION ALL 程式碼較長但邏輯清晰;OR 簡潔但超過 10 條件易讀性下降。