實測環境: 62 萬筆 record 表
| 索引策略 | 范圍查詢 | GROUP BY | IN 查詢 |
|---|---|---|---|
| date 非叢集 | 25 秒 | 55 秒 | 27 秒 |
| date 叢集 | 14 秒 | 28 秒 | 14 秒 |
| (place, date, amount) 複合 | 26 秒 | 27 秒 | <1 秒 |
| (date, place, amount) 複合 | <1 秒 | 11 秒 | <1 秒 |
場景: card (7,896 筆) ↔ account (191,122 筆)
-- 僅聯結 card_no:20 秒
SELECT SUM(a.amount) FROM account a, card b
WHERE a.card_no = b.card_no
-- 加上 account_no:<1 秒
SELECT SUM(a.amount) FROM account a, card b
WHERE a.card_no = b.card_no AND a.account_no = b.account_no
優化器根據聯結條件選擇外部/內部表。充分條件讓優化器選到最小 I/O 成本路徑(外部表匹配行數 × 內部表查找成本)。
查看執行計畫:SET SHOWPLAN_ON 或 DBCC TRACEON(3604, 310, 302) (需 sa)。
| 慢查詢 | 快查詢 (索引生效) |
|---|---|
SUBSTRING(card_no,1,4)='5378' (13秒) | card_no LIKE '5378%' (<1秒) |
amount/30 < 1000 (11秒) | amount < 30000 (<1秒) |
CONVERT(char(10),date,112)='19991201' (10秒) | date = '1999/12/01' (<1秒) |
原則: 將運算移至等號右邊,讓優化器在編譯期即可計算常數。
-- 慢:IN 轉為 OR 策略,建工作表、不走索引
SELECT COUNT(*) FROM stuff WHERE id_no IN ('0','1') -- 23秒 (62萬筆達 220秒)
-- 快:拆分查詢再加總
SELECT COUNT(*) FROM stuff WHERE id_no='0' -- 3秒
SELECT COUNT(*) FROM stuff WHERE id_no='1' -- 3秒
-- 或用預存程序變數累加
SQL 調優本質:寫出優化器可識別的語句 → 充分利用索引 → 減少 I/O → 避免掃表。應用層調優只是冰山一角,深層還涉及資源配置、網路、作業系統調校。