執行計劃是優化器依據 SQL 與統計資訊產生的查詢方案。
關鍵在於:SQL 是否清晰表達意圖?統計資訊是否最新?
定期 UPDATE STATISTICS、檢視 SHOWPLAN 是基本功。
SELECT * FROM dual 與 select * from dual 在優化器眼中是兩條不同語句,產生兩個執行計劃、佔用兩份快取。全團隊統一大小寫、縮排、別名風格,提高計劃重用率。
超過 3 層巢狀子查詢、數頁長的 SQL,優化器極易給出錯誤計劃。
原則:拆解為多步驟、善用暫存表、讓每個查詢單一職責。
將複雜查詢拆解,中間結果寫入 #temp 或表變數:
✅ 避免重複掃描主表
✅ 減少共享鎖阻塞更新鎖
✅ 提高併發效能
WHERE changetime > @chgtime 讓相似查詢重用同一執行計劃,一次解析、多次重用。
ADO.NET 用 Parameters、Java 用 PreparedStatement、存儲程序用參數。
傾斜欄位(如「民族」90% 為漢族)首次傳入「漢族」→ 全表掃描計劃被快取;後續傳入「布依族」本應走索引,卻復用全掃計劃。
對策:傾斜欄位不用綁定變數、或用 OPTION (RECOMPILE)、或建立過濾索引。
BEGIN TRAN 套住的語句越少越好。鎖定資源直到 COMMIT,大交易是併發殺手。
能用觸發器同步資料就別用大交易。
SQL Server 讀寫互斥,NOLOCK 允許髒讀但提高併發。
三不原則:
① 寫入依賴的查詢不可加
② 頻繁頁分裂的表慎用
③ 能用暫存表實現快照隔離就別用 NOLOCK
訂單表以 order_id(遞增)為叢集索引 → 新增寫入尾頁、無頁分裂。
若建在 customer_id(隨機) → 插入導致頁分裂、效能暴跌。
重建叢集索引會消除稀疏空間,可能引發大量頁分裂**,需評估填充因子。
掃描第 100 頁時發生分裂,資料移至 101 頁 → 重複讀;移至 99 頁 → 跳讀。
實務上曾導致主鍵衝突錯誤。
LIKE '%yue%' 必全表掃描。非必要不加前置萬用字元。
SQL Server 2000 參數未強型別傳入 → 自動轉換 → 索引失效。2005+ 改善但仍建議應用層嚴格型別。
| 算子 | 適用場景 | 成本模型 |
|---|---|---|
| Nested Loop | 外表小、內表有索引 | 外表行數 × 內表行數 |
| Merge Join | 雙邊連接欄皆為叢集索引(已排序) | 外表行數 + 內表行數 |
| Hash Join | 無索引、大表關聯 | 建雜湊表 + 掃描 |
優化口訣:連接欄上叢集索引 → 減小結果集 → 還在用 SQL 2000 做大表 JOIN?快升級!