我們已經討論了GAM與SGAM頁,數據頁(Data Page) ,現在我們來看下頁面自由空間頁(Page Free Space (PFS) )。
PFS在數據文件里是第2頁(頁號1,頁號從0開始),接在文件頭(file header,頁號0)后。GAM與SGAM是用來跟蹤區分配情況,而PFS頁是用來跟蹤頁分配級別(page level allocation)。當分配頁時,數據庫引擎使用GAM與SGAM來確定有可用頁的區。一旦數據庫引擎找到有可用頁的區,它使用PFS頁來確定在那個區里未分配的頁,頁里可用空間量是多少。可用空間只對頁存儲LOB值(例如text/image, varchar(max), nvarchar(max), varbinary(max), row overflow data)或堆數據頁時跟蹤。默認情況下,LOB數據保存在獨立的頁,只通過在數據頁保留一個指向獨立頁的指針。在有可用空閑的頁里數據才可以被保存。對於索引頁來說,數據應該和索引順序一樣保存,所以沒有插入記錄指針的說法。也就沒有必要在索引里跟蹤可用空間。
GAM和SGAM都有位圖,但是PFS頁只有字節圖。在PFS頁區間它為每頁保留1位。一個PFS頁可以保存8088頁的可用空間使用信息。
在每字節的每一位代表信息如下:
- 第0-2位:在頁里有多少可用空間
- 0x00:空的,未使用
- 0x01:1%-50%被占用
- 0x02:51%-80%被占用
- 0x03:81%-95%被占用
- 0x04:96%-100%被占用
- 第3位(0x08):頁里是否有1條或多條鬼影記錄(ghost records)
- 第4位(0x10):當前頁是IAM頁么?
- 第5位(0x20):當前頁是混合頁么?
- 第6位(0x40):當前頁是已分配么?
- 第7位:未使用
我們來看一個具體的例子:新建一個數據庫,並使用DBCC PAGE命令查看PFS頁的信息:
1 CREATE DATABASE PFSdb 2 GO 3 USE PFSdb 4 GO 5 DBCC TRACEON(3604) 6 GO 7 DBCC PAGE(PFSdb,1,1,3)
........
可以看到,自180頁到287頁空間沒分配了。
我們往表里插入點數據,再用DBCC PAGE查看下PFS頁的信息:
1 SELECT * INTO SalesOrderHeaderTest FROM AdventureWorks2008R2.Sales.SalesOrderHeader 2 DBCC TRACEON(3604) 3 GO 4 DBCC PAGE(PFSdb,1,1,3)
......
可以看到從288頁到1311頁有新頁添加。
我們現在把表drop掉,再看看PFS頁的信息:
......
可以看到剛才被分配的頁現在變成未分配了,但是空間還是100%被占用。這是因為在頁沒有被重新分配前,PFS字節沒有被完全重設。在重新分配時,數據庫引擎只重設分配狀態位,這可以讓數據庫引擎在回滾重新分配時,通過重設分配狀態位即可。