[SQL SERVER]重視轉發紀錄

開發人員、DBA需要知道什麼是轉發紀錄(Forwarded Records)嗎?

轉發紀錄對效能有影響嗎?

建立設計正確叢集索引是必要嗎?

 

什麼是轉發紀錄(Forwarded Records)

轉發紀錄是用來追蹤資料存放的參考指標(point)。當你更新(增加)欄位資料大小時,如果這時資料超過該頁面(page)大小,

那麼SQL SERVER會將資料移到新頁面,而原本頁面就會留下轉發紀錄,透過該紀錄指標SQL SERVER 才能知道資料存放位置,

慶幸的事,這只會發生在Heap資料表(註1)。

 

為什麼要重視轉發紀錄

真實世界資料更新是普遍的,例如系統初期該欄位(可能設定最大長度為20)中資料最大長度為5,

因為某些(異質)資料內容非預期,這時欄位中資料最大長度可能大於5(為了整合異質平台),

當然有時更新可能會超過一個欄位以上,如果你的資料表為heap,那麼將會嚴重影響查詢效能並浪費硬碟空間。

 

為什麼要建立叢集索引

我前面提到,轉發紀錄只會發生在heap資料表,而之前我執行一些資料庫效能健檢專案,我發現一些有趣的現象,

我發現一些企業主要資料表都沒建立叢集索引,當下我非常好奇想了解原因,

得到答案是因為建立叢集索引影響資料更新效能(insert、update),因為要考慮資料排序(註2)讓他們覺得很麻煩,

但相對查詢效能就會差,這也是為什麼這些企業資料表的非叢集索引基本都15起跳來算。

 

驗證及修復轉發紀錄

select OBJECT_NAME(object_id) as [Table Name], page_count,(page_count*8) as [Table Size(KB)],
forwarded_record_count, avg_fragmentation_in_percent
from sys.dm_db_index_physical_stats (DB_ID(), OBJECT_ID('rsa241_20130821'), default, default, 'DETAILED');

該heap資料表沒有任何轉發紀錄。

 

執行更新作業

update rsa241_20130821
set device_id = device_id+device_id+device_id+device_id+device_id
where num >= 4164403 and num <= 4175403;

這時轉發紀錄數量為360,但頁面沒有增加,表示目前資料並未超過頁面大小。

 

這次把更新範圍加大,並看看頁面和轉發紀錄數量

可以看到轉發紀錄數量大幅增加,頁面數量從24480暴增至25119,由於資料超過該頁面大小,

所以會產生新頁面並在原本頁面留下轉發紀錄指標,SQL SERVER透過指標來參考資料存放位置,

而這些轉發紀錄無疑是在浪費I/O和硬碟空間,這也是為什麼大家都說heap資料表是”虛胖”的因素之一。

 

如何修復

SQL2008以上版本有提供重建heap 資料表,但如要長期避免轉發紀錄浪費I/O,建議所有資料表均建立叢集索引,當然不需要也可不建立。

alter table rsa241_20130821 rebuild

重建完後可以看到頁面數量減少、且轉發紀錄=0。

 

下面驗證nonheap資料表是否會產生轉發紀錄

不管執行多少次更新作業,轉發紀錄數量永遠為null。

 

註1:

Heap 資料表是指資料表不存在叢集索引,這時資料表中資料是隨機並沒有一定順序。

註2:

只要是我經手的專案,建立叢集索引絕對是必要且重要的一件事,

2011年我針對如何決定叢集索引寫了一篇[SQL SERVER][Memo]再談 Clustered Index

錯誤的叢集索引key對效能有巨大影響(硬碟空間也是)。

 

參考

Maximum Capacity Specifications for SQL Server

Understanding Pages and Extents

Row-Overflow Data Exceeding 8 KB

How Forwarded Records are Read and Processed in a SQL Server Heap

Knowing about ‘Forwarded Records’ can help diagnose hard to find performance issues.