非聚集索引內部結構
- B+ 樹結構: 與聚集索引相同,但葉級存儲「索引行」而非「數據行」。
- 行定位器:
- 堆表 → RID (File:Page:Slot)
- 有聚集索引表 → 聚集索引鍵(必要時加 4 字節唯一化值)
- 數據順序: 不遵循非聚集鍵順序物理存儲。
網絡觀點驗證:ORDER BY 列建非聚集索引能否提速?
案例: 千萬級訂單表 order(create_date 唯一、不連續)與會員表 member 關聯,查詢:
SELECT * FROM [order] o
INNER JOIN member m ON o.proxyID = m.proxyID
WHERE o.leaveDate BETWEEN @start AND @end
ORDER BY o.create_date DESC;
測試結果
- 情況一:
create_date 建非聚集索引 → member 表大量掃描(83,588 次),性能差。
- 原因分析: 優化器為避免 Sort 操作,選擇按
create_date 索引順序讀取 order,導致嵌套循環 JOIN 時對 member 重複隨機訪問。
- 結論: 索引順序與 JOIN 訪問路徑衝突時,強制有序輸出反而拖垮整體性能。
核心原則:環境、結構、數據分布決定一切
- 無銀彈: 同一索引在不同查詢/數據量下效果截然不同。
- 綜合評估: 需同時考慮 WHERE 篩選、JOIN 順序、排序需求、選擇率、並行度。
- 測試驗證: 生產級數據量下對比執行計劃、I/O、耗時,才是唯一標準。
優化建議清單
- 高選擇性 WHERE 列 → 索引鍵前段。
- JOIN 列 → 索引鍵或 INCLUDE。
- ORDER BY 列 → 若為查詢尾部且前段已篩選窄,可考慮;否則交給 Sort 運算符(內存/TempDB)。
- 覆蓋索引消除回表,但警惕寫入放大與索引膨脹。
- 定期
UPDATE STATISTICS 與 REBUILD/REORGANIZE 維護統計與碎片。