SQL Server 擁有強大的查詢優化器,但理解 SARG (Search ARGument) 原理才能寫出真正能用上索引的 WHERE 條件。本文系統講解 SARG 定義、優化器工作機制、7 大實戰優化法則與常見誤區實測對比。
形式:列名 操作符 <常數/變量> 或 <常數/變量> 操作符 列名
合格操作符:=, >, <, >=, <=, BETWEEN, IN (部分), LIKE '前綴%'
核心價值:優化器能識別 SARG,將其轉化為 索引查找 而非 索引掃描/表掃描。
| # | 法則 | ✅ SARG 例 | ❌ 非 SARG 例 | 根因 |
|---|---|---|---|---|
| 1 | LIKE 僅前綴通配符可用索引 | name LIKE '張%' | name LIKE '%張' / name LIKE '%張%' | 前導通配符導致索引無法定位 |
| 2 | OR 導致全表掃描 | name='張三' AND age>30 | name='張三' OR age>30 | OR 無法合併索引查找範圍 |
| 3 | 否定/函數破壞 SARG | price > 5000 | NOT (price>5000), ABS(price)<5000, price*2>10000 | 列上運算/函數使索引鍵值不可用 |
| 4 | IN 等價 OR (大列表慎用) | id IN (1,2,3) | id IN (SELECT ...) 子查詢可能退化 | IN 列表過長優化器可能轉表掃描 |
| 5 | 盡量少用 NOT | status = 'active' | status != 'deleted' | 否定謂詞難利用索引 |
| 6 | EXISTS ≈ IN 性能 (實測) | EXISTS (SELECT 1 FROM t2 WHERE t2.id=t1.id) | IN (SELECT id FROM t2) | 現代優化器對兩者等價轉換,統計信息準確時性能一致 |
| 7 | CHARINDEX ≈ LIKE '%...%' (全掃描) | — | CHARINDEX('關鍵字', col)>0 vs col LIKE '%關鍵字%' | 實測 7 秒 vs 7 秒,邏輯讀 7155 vs 7155,無性能差異 |
-- IN 子查詢
SELECT title,price FROM titles WHERE title_id IN (SELECT title_id FROM sales WHERE qty>30)
-- 掃描 18 次,邏輯讀 56
-- EXISTS 子查詢
SELECT title,price FROM titles WHERE EXISTS (SELECT 1 FROM sales WHERE sales.title_id=titles.title_id AND qty>30)
-- 掃描 18 次,邏輯讀 56 (完全一致)
WITH (INDEX(idx_name)) (謹慎,統計信息過期時可能適得其反)UPDATE STATISTICS table / sp_updatestats — 優化器決策基石Ctrl+M / SET SHOWPLAN_ALL ON — 關注 Index Seek vs Scansp_executesql 復用計劃,避免參數嗅探問題 (可用 OPTION (RECOMPILE) 緩解)