索引是關係型資料庫性能的靈魂。統計顯示,超過 80% 的資料庫性能問題源於索引設計不當或維護缺失。本文系統梳理 SQL Server 索引的核心知識體系,涵蓋索引類型選擇、填充因子策略、碎片整理、統計信息維護及自動化維護計畫,助你構建高效穩定的索引體系。
BETWEEN、>、<、>=、<=)ORDER BY)或分組(GROUP BY)WHERE col = value)INCLUDE 子句將非鍵值欄位加入葉層,打造覆蓋索引,不增加索引樹深度。| 查詢模式 | 推薦索引類型 | 關鍵考量 |
|---|---|---|
| 主鍵查找、範圍掃描、排序 | 聚集索引 | 唯一、窄、靜態、遞增 |
| 非主鍵精確匹配、JOIN 條件 | 非聚集索引 | 高選擇性、考慮 INCLUDE |
| 多欄位組合查詢 | 複合非聚集索引 | 欄位順序遵循「等值優先、範圍其次、選擇性高優先」 |
| 全文搜尋 | 全文索引 | 需啟用 Full-Text Search 服務 |
填充因子 指定索引頁面填滿百分比(0-100),預留空間供未來插入/更新使用,減少頁分裂。預設 0 = 100%(填滿)。
| 表/索引特徵 | 建議填充因子 | 說明 |
|---|---|---|
| 極少更新/插入(如數據倉庫維度表) | 100% (0) | 最大化頁面密度,減少 I/O |
| 中等修改頻率(典型 OLTP 業務表) | 80%-90% | 平衡空間利用與分裂頻率 |
| 高頻插入/更新、寬度大、易產生頁分裂 | 70%-80% | 預留更多空間,犧牲讀性能換寫穩定 |
| GUID/UUID 聚集索引(隨機插入) | 70%-80% | 必須預留空間,否則嚴重碎片化 |
ALTER INDEX IX_Orders_CustomerID ON dbo.Orders REBUILD WITH (FILLFACTOR = 80, ONLINE = ON);
| 維度 | INDEX REORGANIZE (重組) | INDEX REBUILD (重建) |
|---|---|---|
| 操作性質 | 線上、單執行緒、就地整理葉頁 | 離線(預設)/ 線上(Enterprise 版),重新建立索引樹 |
| 碎片處理能力 | 僅處理邏輯碎片(頁順序),不回收空間 | 徹底消除邏輯/物理碎片,回收空間,更新統計信息 |
| 鎖定行為 | 短時共享鎖,不阻塞查詢/修改 | 離線模式佔用 Sch-M 鎖,阻塞所有操作;線上模式僅最後階段短暫 Sch-M |
| 適用閾值 | avg_fragmentation_in_percent: 5% - 30% | > 30% 或需變更填充因子/壓縮/分區 |
| 資源消耗 | 低 CPU/IO/日誌 | 高 CPU/IO/日誌(離線模式日誌極少) |
DECLARE @schema sysname, @table sysname, @index sysname, @frag float, @cmd nvarchar(max);
DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
SELECT s.name, t.name, i.name, ips.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
JOIN sys.tables t ON i.object_id = t.object_id
JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE ips.index_id > 0 -- 排除堆表
AND ips.page_count > 1000 -- 忽略小表
AND ips.avg_fragmentation_in_percent > 5;
OPEN cur;
FETCH NEXT FROM cur INTO @schema, @table, @index, @frag;
WHILE @@FETCH_STATUS = 0 BEGIN
IF @frag >= 30
SET @cmd = N'ALTER INDEX ' + QUOTENAME(@index) + N' ON ' + QUOTENAME(@schema) + N'.' + QUOTENAME(@table) + N' REBUILD WITH (ONLINE = ON, MAXDOP = 2);';
ELSE
SET @cmd = N'ALTER INDEX ' + QUOTENAME(@index) + N' ON ' + QUOTENAME(@schema) + N'.' + QUOTENAME(@table) + N' REORGANIZE;';
PRINT @cmd;
EXEC sp_executesql @cmd;
FETCH NEXT FROM cur INTO @schema, @table, @index, @frag;
END
CLOSE cur; DEALLOCATE cur;
AUTO_UPDATE_STATISTICS ON),閾值:表行數 > 500 時,修改量超過 20% + 500 觸發異步更新(可能導致查詢使用舊統計)。UPDATE STATISTICS dbo.Orders WITH FULLSCAN, ALL; 針對關鍵表、大表、參數敏感查詢定期全掃描更新。INCREMENTAL = ON,僅更新變更分區,大幅降低維護開銷。DBCC SHOW_STATISTICS('dbo.Orders', 'IX_Orders_CustomerID'); 關注 Rows Sampled、Steps、Density Vector、Histogram。使用 維護計畫精靈 或 T-SQL Job 實現每日/每週自動化:
DBCC CHECKDB)ONLINE = ON、MAXDOP 限制並行度,避免衝擊核心業務。DATA_COMPRESSION = PAGE 壓縮大型索引,節省 40-60% 空間並減少 I/O。sp_BlitzIndex 或 sys.dm_db_index_usage_stats 清理未使用索引(user_seeks + user_scans + user_lookups = 0)。WHERE varchar_col = 123 觸發 CONVERT_IMPLICIT,改為 WHERE varchar_col = '123'。WHERE YEAR(create_date) = 2023 → 改為 WHERE create_date >= '2023-01-01' AND create_date < '2024-01-01'。索引優化不是一次性動作,而是持續的「監控 → 分析 → 調整 → 驗證」閉環。建立基準線、自動化維護、定期審視執行計畫、配合業務發展調整索引策略,才能讓 SQL Server 持續輸出穩定高效的查詢性能。記住:最好的索引是業務需要的索引,而不是理論上完美的索引。