SQL Server 內建「查詢分析優化器」,自動計算 WHERE 條件選擇最佳索引。**條件順序不影響效能**,優化器會重新排序。但理解 SARG(Search ARGument)機制對編寫高效 SQL 至關重要。
欄位名 運算子 <常數或變數>
或
<常數或變數> 運算子 欄位名
符合 SARG 可利用索引快速定位;不符合需全表掃描逐行判斷。
name LIKE '張%' → SARG,索引有效name LIKE '%張' → 非 SARG,前置 % 導致索引失效Name='張三' AND 價格>5000 → SARGName='張三' OR 價格>5000 → 非 SARG,全表掃描典型非 SARG:NOT、!=、<>、!<、!>、NOT EXISTS、NOT IN、NOT LIKE、函數運算(ABS(價格)<5000)
特例:WHERE 價格*2>5000 可被轉換為 WHERE 價格>2500 視為 SARG,**但不建議依賴**,無法保證完全等價。
SELECT * FROM table1 WHERE tid IN (2,3)
-- 等同於
SELECT * FROM table1 WHERE tid=2 OR tid=3
即使 tid 有索引也會失效。
實測(pubs 資料庫,STATISTICS IO):
-- IN 版本
SELECT title, price FROM titles
WHERE title_id IN (SELECT title_id FROM sales WHERE qty>30)
-- sales: 掃描 18,邏輯讀 56 | titles: 掃描 1,邏輯讀 2
-- EXISTS 版本
SELECT title, price FROM titles
WHERE EXISTS (SELECT * FROM sales WHERE sales.title_id=titles.title_id AND qty>30)
-- sales: 掃描 18,邏輯讀 56 | titles: 掃描 1,邏輯讀 2
I/O 統計完全一致。NOT EXISTS / NOT IN 同理。
-- CHARINDEX:7秒,掃描 4,邏輯讀 7155
SELECT * FROM tgongwen WHERE CHARINDEX('刑偵支隊', reader)>0 AND fariqi>'2004-5-5'
-- LIKE %:7秒,掃描 4,邏輯讀 7155
SELECT * FROM tgongwen WHERE reader LIKE '%'+'刑偵支隊'+'%' AND fariqi>'2004-5-5'
一般情況 UNION 較快:
-- OR:68秒,邏輯讀 404008
SELECT * FROM Tgongwen WHERE fariqi='2004-9-16' OR gid>9990000
-- UNION:9秒,邏輯讀 67489
SELECT * FROM Tgongwen WHERE fariqi='2004-9-16'
UNION
SELECT * FROM Tgongwen WHERE gid>9990000
**但當 OR 兩側查詢同一欄位時,UNION 反而較慢:**
-- OR:6423ms,掃描 2,邏輯讀 14726
SELECT * FROM Tgongwen WHERE fariqi='2004-9-16' OR fariqi='2004-2-5'
-- UNION:11640ms,掃描 8,邏輯讀 14806
SELECT * FROM Tgongwen WHERE fariqi='2004-9-16'
UNION
SELECT * FROM Tgongwen WHERE fariqi='2004-2-5'
原因:UNION 需合併去重,增加額外排序/雜湊開銷。
SELECT TOP 10000 gid, fariqi, reader, title ... -- 4673ms
SELECT TOP 10000 gid, fariqi, title ... -- 1376ms
SELECT TOP 10000 gid, fariqi ... -- 80ms
每減少一欄位,速度顯著提升,幅度取決於欄位大小。
COUNT(*) -- 1500ms
COUNT(gid) -- 1483ms (主鍵)
COUNT(fariqi) -- 3140ms
COUNT(title) -- 52050ms
COUNT(*) 與 COUNT(主鍵) 速度相當,且比其他欄位快。引擎推測自動選最小欄位統計。
無 ORDER BY (fariqi 聚集索引) -- 196ms
ORDER BY gid ASC (主鍵非聚集) -- 4720ms
ORDER BY gid DESC -- 4736ms
聚集索引排序快 3/10。小數據量差異明顯,大數據量(10萬+)差異縮小。
100萬筆:2004/1/1 後 50萬筆(2 個不同日期,精確到日);之前 50萬筆(5000 個不同日期,精確到秒)。
fariqi > '2004-1-1' ORDER BY fariqi -- 6390ms
fariqi < '2004-1-1' ORDER BY fariqi -- 6453ms
結論:日期含時分秒**不降低**查詢速度。