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

MSSQL Server 查詢優化完整指南:從索引設計到硬體調校

     編輯:關於SqlServer

查詢緩慢十大常見成因

  1. 缺乏索引或索引未被使用(最常見,屬設計缺失)
  2. I/O 吞吐瓶頸:磁碟讀寫速度跟不上
  3. 未建立計算欄位導致查詢無法優化
  4. 記憶體不足:緩衝池壓力大,頻繁磁碟交換
  5. 網路延遲:客戶端與伺服器傳輸緩慢
  6. 回傳資料量過大:應分頁或分批查詢
  7. 鎖爭用/死鎖:讀寫競爭資源(sp_lock, sp_who 診斷)
  8. 回傳不必要的行/列:浪費 I/O 與網路頻寬
  9. 查詢語句未優化:邏輯效率低、掃描過多資料頁

系統層面優化策略

1. 存儲架構分離

  • 資料、記錄、索引放置不同 I/O 設備(如獨立磁碟/RAID 陣列)
  • TempDB 放置於高速儲存(舊版建議 RAID 0,SQL 2000+ 不再支援)
  • 資料量越大,I/O 隔離效益越明顯

2. 資料表拆分

  • 垂直拆分:將大欄位(text/image/長 varchar)移至副表,主表保留高頻欄位
  • 水平拆分:依範圍/雜湊分割歷史/熱門資料,縮小單表體積(sp_spaceuse 監控)

3. 硬體升級

  • 擴充記憶體:Win2000 + SQL 2000 支援 4-8GB;虛擬記憶體設為實體 1.5 倍,啟用全文檢索則 3 倍
  • 增加 CPU:並行查詢(排序、連接、掃描、GROUP BY)自動由優化器決定;注意 UPDATE/INSERT/DELETE 不支援並行

4. 索引優化核心原則

  • 依查詢條件建立索引,優化存取路徑,限制結果集大小
  • 填充因子預設 0 通常最佳;索引越窄越好(位元組少的欄位優先)
  • 避免對低基數欄位(如性別)建單一索引
  • 定期重建:DBCC REINDEX、DBCC INDEXDEFRAG;收縮:DBCC SHRINKDB/FILE
  • 大型資料庫關閉自動增長,手動規劃空間避免效能抖動

T-SQL 撰寫黃金法則

查詢優化器處理流程

  1. 詞法/語法檢查
  2. 提交查詢優化器
  3. 代數優化 + 存取路徑優化
  4. 預編譯產生查詢計畫
  5. 排程執行
  6. 回傳結果

資料儲存結構

  • 頁面 8KB (8060 位元組可用),8 頁 = 1 區 (64KB),B-tree 結構組織

關鍵寫法優化 40+ 條

#優化要點說明/範例
1WHERE 限制回傳行數避免全表掃描,大表掃描期間鎖表阻塞其他存取
2避免游標改用客戶端迴圈、暫表、Table 變數、子查詢、CASE 陳述式
3UNION ALL 替代 UNIONUNION 需排序去重,ALL 直接合併,效能差異大
4慎用 DISTINCT / ORDER BY可移至客戶端處理,減少伺服器排序開銷
5LIKE 模式索引利用LIKE 'a%' 用索引;LIKE '%a'、LIKE '%a%' 全掃描 → 長字串改全文索引
6欄位運算移至等號右側WHERE SUBSTRING(name,1,1)='m' → WHERE name LIKE 'm%'
7IN/OR 拆解為 UNION ALL多 OR 條件未用索引時,改寫 UNION ALL 再嘗試匹配索引
8指定索引提示SELECT * FROM Table (INDEX=IX_Name) WHERE col IN (...)
9預先計算結果存表複雜報表/費用計算預聚合,查詢時直接 SELECT
10MIN/MAX 善用索引合適索引下極值查詢極快
11程式碼貼近資料優先順序:Default → Rule → Trigger → Constraint → Procedure
12大二進位用預存程序避免應用層雙向轉換(二進位↔字串),直接傳參數
13BETWEEN 優於 IN範圍查詢索引定位更快
14臨時表索引視情況建立索引也消耗資源,非必然提升
15必要時才用事務報表查詢勿加事務,浪費鎖資源
16視圖慎用、禁嵌套視圖本質為優化後 SQL,嵌套增加解析開銷;單表查詢直取基表
17IN 列表頻繁值前置減少判斷次數
18避免 SELECT INTO 鎖系統表建表用明確 CREATE TABLE;事務中禁用 SELECT INTO
19GROUP BY/HAVING 後置WHERE 先篩選 → GROUP BY 分組 → HAVING 篩選分組
20批次更新優於逐筆單一 UPDATE 多列優於多次 UPDATE
21Table 變數替代臨時表輕量、無鎖系統表、自動清理
22計算欄位可索引 (2000+)需確定性運算式、非 LOB 型別、ANSI_NULLS/PADDING ON
23邏輯運算下推伺服器用預存程序減少網路往返;UDF 回傳大結果集改用預存程序
24重複函數呼叫提取變數避免重複計算
25COUNT(*) 效能低改用 EXISTS;注意 COUNT(nullable) vs COUNT(not null) 結果不同
26執行緒池配置記憶體足:執行緒=最大連接+5;否則啟用執行緒池
27固定鎖定順序防死鎖所有預存程序依相同順序鎖表(先 A 後 B)

效能監控關鍵計數器

物件計數器警示閾值/建議
MemoryPage Faults/sec持續偏高 → 記憶體瓶頸
Processor% Processor Time>95% 持續 → CPU 瓶頸,增 CPU 或換更快 CPU
Processor% User Time高 → 增索引、簡化聯接、水平分割大表
PhysicalDiskCurrent Disk Queue Length> 1.5-2 倍磁碟數 → 加磁碟/RAID
SQLServerCache Hit Ratio<80% 持續 → 加記憶體(注意累計值需重啟後觀察)

進階技巧精選

  • 隱式轉換殺手:WHERE salary > 3000 (salary=float) → 優化器轉 CONVERT(float,3000),寫成 3000.0 避免轉換
  • 連接順序影響計畫:提供完整等價條件(A=B, B=常數, A=常數)助優化器推導
  • 動態條件寫法:無參數時全表掃描 SELECT * FROM T;有參數時 SELECT * FROM T WHERE col=@val,等值查詢最快
  • 分頁新法:Table 變數 + IDENTITY + TOP N,依瓶頸類型(I/O vs CPU)選擇排序欄位

總結

查詢優化是系統工程:20% 代碼消耗 80% 資源,聚焦慢查詢;索引設計、查詢改寫、硬體資源、監控告警四位一體。善用 Query Analyzer/Profiler 觀察實際執行計畫,持續迭代優化。

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