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

SQL Server Forwarded Record 計數器飆高導致 IO 效能惡化:成因與解決之道

     編輯:關於SqlServer

近期於客戶環境觀察到 Forwarded Records/Sec 計數器持續偏高,伴隨磁碟等待佇列間歇性波動。本文深入剖析 Forwarded Record 形成機制、為何會產生額外 IO 開銷,並提供徹底解決方案。

一、什麼是 Forwarded Record?

當資料以 堆積表 儲存時,資料無序排列,非叢集索引的指標指向物理位置的 RID。若資料列中的變長欄位更新導致資料行超過頁面剩餘空間,SQL Server 會將該列移動至新頁面,在原位置留下一個 16 位元組的轉發指標指向新位置。此機制旨在避免更新時同步修改所有非叢集索引的指標。

Forwarded Record 示意圖

二、為何會拖垮 IO 效能?

雖然 Forwarded Record 減少更新開銷,但查詢端卻付出代價:

  • 表掃描:需追蹤每個轉發指標,邏輯讀取次數成倍增加。
  • 書籤查找:非叢集索引尋找後仍需跟隨指標跳轉,產生額外隨機 IO。
  • 頁面不連續:轉發頁面常與原頁面物理不連續,挑戰 IOPS 能力。

實測重現

-- 建立堆積表並插入 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

初始空間佔用:590 頁

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

產生 8 萬+ Forwarded Record 掃描 590 頁卻產生 8 萬+ 邏輯讀取 效能計數器顯示 Forwarded Records/Sec 飆升

三、解決方案

  1. 建立叢集索引(首選):OLTP 系統所有表皆應有叢集索引。叢集索引將資料依鍵值排序,更新時直接就地修改或分頁,不會產生 Forwarded Record。
  2. 表重建:若無法建立叢集索引,可執行 ALTER TABLE ... REBUILD 或 CREATE CLUSTERED INDEX ... WITH (DROP_EXISTING = ON) 整理頁面、消除轉發指標。
  3. 評估表設計:僅「寫入為主、極少讀取」的暫存表適合堆積表;一旦出現 Forwarded Record 即代表有讀取壓力,應轉為叢集索引表。
最佳實務:在維護視窗期間為問題表建立叢集索引,並配合 FILLFACTOR 預留空間減少未來頁面分割。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved