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

SQL Server 索引管理六大鐵律:從建立策略到維護實務的完整法則

     編輯:關於SqlServer

索引是加速查詢的利器,也是寫入效能的負擔。本文提煉六大索引管理鐵律,涵蓋成本認知、欄位選擇、範圍查詢、主外鍵、特殊型別、WHERE 子句融合,並提供實務檢核表與維護腳本。

鐵律一:天下沒有免費午餐 — 索引有成本

  • 寫入開銷: 每次 INSERT/UPDATE/DELETE 需同步維護所有相關索引 B+ 樹,寫入放大效應明顯。
  • 儲存空間: 非叢集索引獨立儲存鍵值 + RID/叢集鍵,大表索引常超過資料本身。
  • 維護負擔: 重建/重組索引、更新統計資訊佔用 CPU、I/O、鎖定資源。
  • 優化器負擔: 索引過多導致計畫搜尋空間爆炸,編譯時間延長。

原則: 每個索引必須有明確「付費查詢」支撐,定期清理未被使用的索引 (sys.dm_db_index_usage_stats)。

鐵律二:低選擇性、低頻查詢欄位 — 不建索引

欄位類型範例理由
極低基數性別 (M/F)、狀態碼 (0/1/2)、布林旗標掃描比例超過 30% 時優化器傾向全表掃描,索引無效
極高重複值公司代碼 (單一租戶)、預設分類同低基數,區分度不足
極少用於 WHERE/JOIN/ORDER BY備註、描述、建立時間 (僅顯示不篩選)維護成本 > 查詢收益

例外: 覆蓋索引 INCLUDE 欄位可包含低選擇性欄位,避免 Key Lookup。

鐵律三:高頻範圍查詢欄位 — 必建索引

  • 日期區間:WHERE OrderDate BETWEEN @Start AND @End
  • 數值區間:WHERE Price BETWEEN 100 AND 500
  • 字首比對:WHERE Name LIKE 'Zhang%' (非前置萬用字元)

索引天然有序,範圍掃描只需定位起點、順序讀取葉節點,極度高效。搭配 TOP N 可進一步縮短回傳路徑。

鐵律四:主鍵與外鍵 — 必須建立索引

  • 主鍵: 自動建立唯一叢集/非叢集索引,保證實體唯一與邏輯定位。
  • 外鍵: SQL Server 不自動建立 FK 索引!無索引時,父表刪除/更新需掃描整張子表驗證参照完整性,產生嚴重鎖爭用與阻塞。

-- 必須手動為 FK 欄位建立索引
CREATE NONCLUSTERED INDEX IX_Orders_CustomerID ON Sales.Orders(CustomerID);
-- 若常用複合條件
CREATE NONCLUSTERED INDEX IX_Orders_Cust_Date ON Sales.Orders(CustomerID, OrderDate);

鐵律五:大型物件型別 (LOB) — 謹慎建立索引

若業務極度依賴大欄位精確比對 (如合約全文比對),考慮計算欄位存雜湊值 (CHECKSUM/HASHBYTES) 並建立索引。

鐵律六:索引與 WHERE 子句融為一體 — SARGable 設計

索引鍵順序應匹配查詢模式:


-- 查詢模式:WHERE CustomerID = @Cust AND OrderDate BETWEEN @S AND @E
-- 最佳索引:(CustomerID, OrderDate) — 等值在前,範圍在後
CREATE INDEX IX_Orders_Cust_Date ON Sales.Orders(CustomerID, OrderDate) INCLUDE (TotalAmount);
  • 等值條件欄位置於索引鍵前段
  • 範圍條件欄位置於等值之後
  • SELECT/ORDER BY/GROUP BY 欄位納入 INCLUDE 實現覆蓋索引
  • 避免在索引欄位上做運算/函數:WHERE YEAR(OrderDate)=2024 → 改為範圍查詢

索引維護實務腳本


-- 1. 偵測未使用索引 (保留 30 天以上無 user_seeks/scans/lookups)
SELECT 
    OBJECT_NAME(i.object_id) AS TableName,
    i.name AS IndexName,
    i.type_desc,
    s.user_seeks, s.user_scans, s.user_lookups,
    s.last_user_seek, s.last_user_scan
FROM sys.indexes i
LEFT JOIN sys.dm_db_index_usage_stats s ON i.object_id=s.object_id AND i.index_id=s.index_id
WHERE i.type > 0  -- 排除堆疊
  AND (s.user_seeks+s.user_scans+s.user_lookups) = 0
  AND i.name IS NOT NULL;

-- 2. 碎片整理 (線上/離線視版本與版本)
-- 碎片 5-30% → REORGANIZE;>30% → REBUILD
-- 建議使用 Ola Hallengren 維護方案或 Maintenance Plan

索引設計檢核表

  1. 是否有查詢使用此欄位組合?(查詢計畫驗證)
  2. 欄位選擇性是否足夠?(密度 < 1% 為佳)
  3. 是否為 FK 欄位?(必建)
  4. 是否為 LOB 型別?(一般不建)
  5. 索引鍵順序是否匹配 WHERE 等值→範圍順序?
  6. 是否需 INCLUDE 覆蓋查詢欄位?
  7. 叢集索引是否已佔用最佳欄位?(避免 PK 自動佔用)
  8. 是否規劃定期重建/統計更新?

索引管理是持續迭代過程:監控 → 分析 → 調整 → 驗證。將六大鐵律內化為審查標準,能讓資料庫長期保持最佳效能狀態。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
型別特性建議
TEXT / NTEXT / IMAGE已棄用,行外儲存,長度不定不可建索引,遷移至 VARCHAR(MAX)/VARBINARY(MAX)
VARCHAR(MAX) / NVARCHAR(MAX) / VARBINARY(MAX)行外儲存,可能極大一般不建索引;極少數全文搜尋需求用全文索引
XML結構化大物件使用 XML 索引 (主 XML 索引 + 次要索引)