查詢效能優化核心三板斧:改寫邏輯、建立覆蓋索引、維護統計資料。本文以實測數據示範逐步優化過程。
EXISTS 只需判斷是否存在,遇真即停;IN 需掃描完整子查詢結果集。NOT IN 含 NULL 時語意陷阱且全表掃描;NOT EXISTS 安全高效。t_userinfo:userid (PK), nick, classid, writetime。CREATE TABLE t_userinfo (
userid INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED,
nick VARCHAR(50) NOT NULL DEFAULT '',
classid INT NOT NULL DEFAULT 0,
writetime DATETIME NOT NULL DEFAULT GETDATE()
);
CREATE INDEX IX_t_userinfo_classid_writetime
ON t_userinfo (classid, writetime) INCLUDE (nick);
-- 查詢:SELECT nick FROM t_userinfo WHERE classid = 5 ORDER BY writetime DESC
-- 可直接由索引滿足,無需鍵查閱
-- 原始:相關子查詢逐列執行
SELECT u.nick, (SELECT COUNT(*) FROM t_userinfo v WHERE v.classid = u.classid) AS Cnt
FROM t_userinfo u WHERE u.userid = 100;
-- 優化:衍生表聯結
SELECT u.nick, agg.Cnt
FROM t_userinfo u
JOIN (SELECT classid, COUNT(*) AS Cnt FROM t_userinfo GROUP BY classid) agg
ON u.classid = agg.classid
WHERE u.userid = 100;
-- 每日低峰期執行
UPDATE STATISTICS t_userinfo WITH FULLSCAN;
-- 或啟用資料庫層級
ALTER DATABASE TestDB SET AUTO_UPDATE_STATISTICS ON;
ALTER DATABASE TestDB SET AUTO_UPDATE_STATISTICS_ASYNC ON; -- 非同步更新,避免查詢等待
| 查詢模式 | 耗時 (ms) | IO (邏輯讀取) |
|---|---|---|
| 子查詢 + 無索引 | 12,450 | 1,240,000 |
| 聯結 + 覆蓋索引 | 18 | 12 |