近期於客戶環境觀察到 Forwarded Records/Sec 計數器持續偏高,伴隨磁碟等待佇列間歇性波動。本文深入剖析 Forwarded Record 形成機制、為何會產生額外 IO 開銷,並提供徹底解決方案。
當資料以 堆積表 儲存時,資料無序排列,非叢集索引的指標指向物理位置的 RID。若資料列中的變長欄位更新導致資料行超過頁面剩餘空間,SQL Server 會將該列移動至新頁面,在原位置留下一個 16 位元組的轉發指標指向新位置。此機制旨在避免更新時同步修改所有非叢集索引的指標。

雖然 Forwarded Record 減少更新開銷,但查詢端卻付出代價:
-- 建立堆積表並插入 10 萬筆 BEGIN TRAN DECLARE @index INT = 1; WHILE @index < 100000 BEGIN INSERT INTO dbo.HeapTest (id, col1) VALUES (@index, NULL); SET @index += 1; END COMMIT

-- 更新導致資料行增長,產生大量 Forwarded Record
UPDATE dbo.HeapTest SET col1 = REPLICATE('X', 2000);

ALTER TABLE ... REBUILD 或 CREATE CLUSTERED INDEX ... WITH (DROP_EXISTING = ON) 整理頁面、消除轉發指標。最佳實務:在維護視窗期間為問題表建立叢集索引,並配合 FILLFACTOR 預留空間減少未來頁面分割。