面對千萬級資料表,查詢效能優化不再是參數調整,而是邏輯重構。本文彙總 24 條優化鐵律,並以「IN 條件 + 資料傾斜」實戰案例,示範如何從資料分布切入,選擇叢集索引而非非叢集索引,將邏輯讀從百萬級降至千級。
WHERE num = 0。UNION ALL 或篩選正向條件。UNION ALL 分開查詢合併。BETWEEN;大量離散值考慮 EXISTS 或臨時表 JOIN。LIKE '%abc%' 無法用索引。LIKE 'abc%' 可用。WHERE num = @num 編譯時未知值 → 全表掃描。加 WITH (INDEX(idx_name)) 強制。F1/2=100 → F1=200;SUBSTRING(col,1,4)='5378' → col LIKE '5378%';DATEDIFF(yy,dob,GETDATE())>21 → dob < DATEADD(yy,-21,GETDATE())。運算移至等號右側。EXISTS (SELECT 1 FROM B WHERE B.num=A.num) 避免大量鎖定掃描。SELECT INTO (減少 Log);小量用 CREATE TABLE + INSERT (緩和系統表壓力)。TRUNCATE TABLE #t; DROP TABLE #t; 避免長時間鎖定系統表。SET NOCOUNT ON,結尾 OFF,減少 DONE_IN_PROC 網路往返。IN 條件優化aa_001 約 1000 萬列,ip 欄位查詢:SELECT * FROM aa_001 WHERE ip IN (1,2,3) ORDER BY name DESC。IN 清單長度不固定。SELECT ip, COUNT(*) FROM aa_001 GROUP BY ip ORDER BY 2;
三類分布:
ip 非叢集索引即可,極快。測試環境:[dbo].[[zping.com]]] 200 萬列,userid 欄位 379 個 distinct 值,頻率 1 ~ 15 萬,嚴重傾斜 (類型 2/3)。
-- 建立 userid 叢集索引
CREATE CLUSTERED INDEX IX_userid ON [dbo].[[zping.com]] (userid);
-- 再次查詢
SELECT * FROM [dbo].[[zping.com]]
WHERE userid IN ('id1','id2','id3')
ORDER BY Ruleid DESC;
結果:
(userid, Ruleid) 覆蓋索引,但 DML 維護成本高,不建議)。IN + 排序 大量回傳的關鍵。