優化器能利用索引的前提是 WHERE 條件為 SARGable:column <op> constant,且 column 參與運算的「原樣」出現。
| 類別 | 操作符/函數 | 失效原因 |
|---|---|---|
| 否定邏輯 | NOT, <>, NOT IN, NOT EXISTS, NOT LIKE | 需掃描全表確認「不匹配」 |
| 隱式/顯式轉換 | CONVERT(), CAST(), UPPER(), LOWER(), RTRIM(), ISNULL(), COALESCE() | 列參與運算,無法直接對比索引鍵值 |
| 運算表達式 | col + 1 = 5, col * 2 > 10, ABS(col) = 5 | 同左,列被計算 |
| LIKE 通配符前置 | LIKE '%abc', LIKE '%abc%' | B-Tree 只能從左匹配 |
-- 失效:列上有函數
SELECT * FROM Orders WHERE YEAR(OrderDate) = 2023;
-- 生效:改為範圍查詢
SELECT * FROM Orders
WHERE OrderDate >= '2023-01-01' AND OrderDate < '2024-01-01';
WHERE ISNULL(col, '') = '' → WHERE col IS NULL OR col = ''(配合篩選索引)。WHERE UPPER(name) = 'ABC' → WHERE name = 'ABC' COLLATE Latin1_General_CI_AI 或建立計算欄索引。WHERE col NOT IN (subquery) → WHERE NOT EXISTS (SELECT 1 FROM ... WHERE ...)。WHERE col LIKE '%kw%' → 全文索引 / 外部搜尋引擎(Elasticsearch)。ALTER TABLE Orders ADD OrderYear AS YEAR(OrderDate) PERSISTED;
CREATE INDEX IX_Orders_OrderYear ON Orders(OrderYear);
查詢 WHERE OrderYear = 2023 即可 Seek。
「列不參與運算、不做隱式轉換、不加前置萬用字元、優先用 EXISTS 代替 NOT IN」—— 守住四條,索引失效少八成。