開發人員、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.