首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

資料庫調優筆記系列(二):查詢寫作黃金法則

     編輯:關於SqlServer

1. 條件順序跟隨複合索引定義順序

複合索引 `(A, B, C)` 的 B 樹導航依賴前綴匹配。WHERE 條件雖順序不影響邏輯結果,但**寫法順序影響優化器統計資訊使用與計畫穩定性** (特別是舊版/參數嗅探場景)。習慣按索引順序寫:`WHERE A=@a AND B=@b AND C=@c`。

2. 循環 + EXISTS → 複合索引 + 集合化

程式碼 `foreach` 迴圈呼叫 `IF EXISTS` → N 次往返。重構:在表上建立複合索引覆蓋 `EXISTS` 條件欄位,將迴圈邏輯下推為單一 `MERGE`/`INSERT...SELECT...WHERE NOT EXISTS`。`IF NOT EXISTS` 改寫為 `IF EXISTS` 以利用索引 (NOT EXISTS 易導致掃描)。

3. 拒絕 SELECT *,擁抱覆蓋索引

  • 傳回無用欄位 → 網路/記憶體/序列化浪費。
  • 觸發 `Bookmark/Key Lookup` → 雙重 B 樹查找、隨機 I/O。
  • **最佳**:查詢欄位 ⊆ 索引鍵 + INCLUDE 欄位 → **索引覆蓋**,純索引掃描/尋找,零 Lookup。

4. 大量 vs 少量回傳的效能排序 (實戰經驗則)

回傳量效能排序 (佳 → 差)
多列 (大結果集)索引覆蓋 > 叢集索引掃描 > 表掃描 > 堆積非叢集索引 > 叢集非叢集索引
少列 (小結果集)索引覆蓋 = 叢集索引尋找 > 堆積非叢集索引 > 叢集非叢集索引 > 表掃描

解讀:叢集表非叢集索引雙重 B 樹 (Key Lookup) 代價高,大結果集下甚至劣於表掃描。**覆蓋索引一統江湖**。

5. WHERE 條件 SARGable 化

  • **拒絕欄位加函數**:`WHERE YEAR(DateCol)=2023` → `WHERE DateCol >= '2023-01-01' AND DateCol < '2024-01-01'`。
  • **運算符移至右側**:`WHERE Price * 1.1 > 100` → `WHERE Price > 100 / 1.1` (避免隱含轉換、啟用索引尋找)。
  • **隱含轉換殺手**:`VARCHAR` 欄位比較 `NVARCHAR` 參數 → 索引失效。參數型別**嚴格匹配**欄位型別。

6. 限制回傳行數與欄數

分頁查詢必加 `OFFSET ... ROWS FETCH NEXT ... ROWS ONLY` (SQL 2012+) 或 `TOP`。避免全表掃描傳回海量資料導致 OOM/Timeout。

總結

查詢寫作不是隨意拼湊,而是**依索引設計反推條件結構、欄位投影、分頁邏輯**的工程紀律。牢記:索引決定查詢形態,查詢驗證索引價值。雙向對齊,才是高效 SQL 的秘訣。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved