漢語字典正文**按拼音排序**,正文本身就是目錄。查「安」字,自然翻到前面;查「張」字,翻到後面。**資料物理順序 = 索引邏輯順序**。一張表**只能有一個**叢集索引,因為資料只能有一種物理排序。
不認識字音時,查「部首目錄」→ 找到頁碼 → 翻到正文該頁。目錄與正文分離,**目錄儲存 (鍵值, 頁碼/書籤)**。**一張表可建多個非叢集索引**(最多 999 個,含 XML/空間索引)。
| 特性 | 叢集索引 | 非叢集索引 |
|---|---|---|
| 資料儲存 | 葉層 = 完整資料列 | 葉層 = 索引鍵 + 書籤 (RID 或叢集鍵) |
| 每表數量 | 1 | 最多 999 |
| 預設建立 | 主鍵預設建叢集 | 唯一約束預設建非叢集 |
| 範圍查詢 | 極快(連續頁) | 需書籤查找,較慢 |
| 插入/更新 | 可能造成頁分裂 | 需同步維護所有非叢集索引 |
| 覆蓋索引 | 天然覆蓋所有欄位 | 需 INCLUDE 欄位才能覆蓋 |
| 動作/場景 | 叢集索引 | 非叢集索引 |
|---|---|---|
| 欄位經常 GROUP BY / ORDER BY | ✅ 適合 | ✅ 適合 |
| 範圍查詢 (BETWEEN, >, <) | ✅ 適合 | ❌ 不適合 |
| 極少唯一值 (如性別、狀態) | ❌ 不適合 | ❌ 不適合 |
| 少量唯一值 (如部門代碼) | ✅ 適合 | ❌ 不適合 |
| 大量唯一值 (如身分證、流水號) | ❌ 不適合 | ✅ 適合 |
| 頻繁 UPDATE 的欄位 | ❌ 不適合 | ✅ 適合 |
| 外鍵欄位 | ✅ 適合 | ✅ 適合 |
| 主鍵欄位 | ✅ 適合 | ✅ 適合 |
非叢集索引葉層包含查詢所需**所有欄位**,查詢無需回表(Key Lookup / RID Lookup)。
CREATE NONCLUSTERED INDEX IX_Orders_CustDate_Cover
ON Orders (CustomerID, OrderDate)
INCLUDE (TotalAmount, Status); -- 非鍵欄位只存在葉層,不參與排序
針對特定子集建立索引,縮小索引體積、減少維護成本。
CREATE NONCLUSTERED INDEX IX_Orders_Active
ON Orders (OrderDate)
WHERE Status = 'Active'; -- 只索引有效訂單
IDENTITY、NEWSEQUENTIALID() 減少頁分裂、碎片。無叢集索引的表稱為堆積。資料無序儲存,非叢集索引書籤為 RID (File:Page:Slot)。適合:純載入暫存表、日誌表、極少查詢的歸檔表。
sys.dm_db_index_physical_stats 檢測 avg_fragmentation_in_percent > 30% → REBUILD;5-30% → REORGANIZE。sys.dm_db_missing_index_* DMV 分析優化器記錄的缺失索引請求。sys.dm_db_index_usage_stats 找出 user_seeks + user_scans + user_lookups = 0 的索引,評估刪除。UPDATE STATISTICS 全掃描。新增索引前問自己: 1. 查詢模式?範圍/排序 → 叢集;精確/連接 → 非叢集 2. 欄位基數?高 → 非叢集;中低但範圍查 → 叢集 3. 更新頻率?高 → 避免叢集,謹慎非叢集 4. 是否覆蓋?加 INCLUDE 消除 Key Lookup 5. 是否可篩選?WHERE 固定值 → FILTERED INDEX 6. 叢集鍵是否窄/唯一/遞增/靜態?否 → 重新設計