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

深度解析 SQL Server 資料頁面頭部結構:DBCC PAGE 實戰教學

     編輯:關於SqlServer

實驗環境建立


IF OBJECT_ID('Test') IS NOT NULL DROP TABLE Test;
GO
CREATE TABLE Test (Id INT, Birth DATETIME, Name CHAR(10));
INSERT INTO Test SELECT 1, '2009-11-27', 'aaaa' UNION ALL SELECT 2, '2009-11-27', 'aaaa';
EXEC sp_spaceused 'Test';
-- 結果:2 列,保留 16KB,資料 8KB,索引 8KB

定位資料頁


DBCC IND('TestDB', 'Test', 0); -- 列出所有頁,找 PageType=1 (資料頁),假設 PageId=89
DBCC TRACEON(3604); -- 輸出導向用戶端
DBCC PAGE('TestDB', 1, 89, 1); -- 資料庫ID=1, 檔案ID=1, 頁碼=89, 輸出選項=1 (頁頭+資料)

頁面頭部關鍵欄位完整解析

欄位範例值含義
m_pageId(1:89)頁面編號 (檔案號:頁號)
m_headerVersion1頭部版本,SQL 7.0 後固定為 1
m_type1頁面類型:1=資料頁、2=索引頁、10=IAM 頁...
m_typeFlagBits0x4資料/索引頁為 0x4,其他為 0
m_level0B 樹層級,0=葉層
m_flagBits0x8000頁面旗標 (如鬼魂記錄、備份標記等)
m_objId / m_indexId83 / 256舊版儲存單元 ID 組成
Metadata: AllocUnitId72057594043367424儲存單元 ID (新版統一識別)
Metadata: PartitionId72057594038386688分區 ID
Metadata: IndexId0索引 ID (0=堆積表)
Metadata: ObjectId2089058478物件 ID (`OBJECT_ID('Test')`)
m_prevPage / m_nextPage(0:0)雙向鏈表指標,資料頁串聯順序
pminlen26固定長度資料最小長度 (含 4 字節列開銷)
m_slotCnt2頁面列數 (槽位數)
m_freeCnt8034頁面剩餘可用空間 (位元組)
m_freeData154從頁首到最後一列資料結尾的位移
m_reservedCnt0作用中交易保留的空間
m_lsn(30:170:20)最後修改日誌序號 (LSN)
m_xactReserved0最新加入保留空間的交易位元組數
m_xdesId(0:0)最近加入保留空間的交易描述符 ID
m_ghostRecCnt0鬼魂記錄數 (已刪除待清理)
m_tornBits0頁面校驗和 / torn page 偵測位元

關鍵數值驗證:手算頁面佈局

1. pminlen = 26

4 字節列開銷 (狀態位元、長度、NULL 位圖指標)
+ 4 字節 INT (Id)
+ 8 字節 DATETIME (Birth)
+ 10 字節 CHAR(10) (Name)
= 26 字節 ✓

2. m_freeData = 154

96 字節頁面頭部固定大小
+ (7 字節槽位陣列開銷/列? 實為 2 字節/列槽位陣列 + 列資料開銷) * 2 列
實際計算:96 (頭部) + 2*2 (槽位陣列) + 2*26 (列資料) = 96 + 4 + 52 = 152
DBCC 輸出 154,差 2 字節可能含版本資訊/保留欄位,大體吻合。

3. m_freeCnt = 8034

8192 (8KB 頁面總大小) - 154 (m_freeData) - 4 (2 列槽位陣列 2*2) = 8034 ✓

4. m_slotCnt = 2

頁面實際儲存 2 列資料 ✓

結構變更 (ALTER TABLE) 對頁面佈局的影響

  • 無結構變更:資料緊湊排列 → 頭部 → 列1 → 列2 → 空閒空間 → 槽位陣列。`m_freeData` = 頭部+列資料+槽位陣列 總長。
  • 有結構變更 (如新增欄位) 且未重建**:舊列保留原位,新欄位資料附加在列尾或透過轉發指標,`m_freeData` 會包含額外的「變更記錄區」,導致空間碎片化。這也是為什麼大型表 ALTER TABLE 需謹慎、建議離線重建的原因。

實務應用場景

  • **空間壓縮評估**:透過 `m_freeCnt`/`m_slotCnt` 計算平均列大小、頁面填滿度。
  • **碎片診斷**:配合 `sys.dm_db_index_physical_stats` 分析頁面分裂、轉發記錄。
  • **損壞修復**:`m_tornBits`/`m_lsn` 協助判斷頁面一致性。
  • **內部原理教學/研究**:理解儲存引擎核心佈局。

總結

資料頁頭部是 SQL Server 儲存引擎的「元資料中樞」。透過 `DBCC PAGE` 解析 `pminlen`、`m_freeData`、`m_freeCnt`、`m_slotCnt` 等核心欄位,可精確重構頁面佈局、驗證空間計算、診斷碎片與結構變更影響。掌握頁面結構,是進階效能調校、災難恢復、核心引擎研究的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved