我們知道SQL Server在8K 的頁里存儲數據。分區就是物理上連續的8個頁。當我們創建一個數據庫,數據文件會被邏輯分為頁和區,當用戶對象創建時,頁會分配給它用來存儲數據。GAM(Global Allocation Map)和SGAM(Shared Global Allocation Map)頁用來跟蹤SQL Server里空間分配情況。這里我們會一起討論下SQL Server的空間分配,還有GAM和SGAM怎么幫助我們分配空間。
在SQL Server里有2類區:
統一區(Uniform Extent) :區屬于一個用戶對象。這些區的所有8頁歸一個對象所有。
混合區(Mixed Extent) :區屬于各個用戶對象。即區里的每個頁都可以屬于不同用戶對象。
為了更好的管理空間分配,如果一個表或索引大小小于8頁(即64k),SQL Server會分配混合區的頁,而不是統一區的頁。
我們在SQL Server里驗證下。
新建一個表(這個表剛好一條記錄一個頁面),并插入26條記錄,并通過DBCC IND查看這個表的相關頁面:
1 USE InternalStorageFormat 2 GO 3 4 IF EXISTS ( SELECT * 5 FROM sysobjects 6 WHERE id = OBJECT_ID(N'[dbo].[TestSpaceAllocation]') 7 AND OBJECTPROPERTY(id, N'IsUserTable') = 1 ) 8 DROP TABLE dbo.TestSpaceAllocation 9 10 CREATE TABLE TestSpaceAllocation(11 Name CHAR(8000)12 )13 GO14 15 INSERT INTO TestSpaceAllocation VALUES('Woody')16 GO 2617 18 DBCC IND('InternalStorageFormat','TestSpaceAllocation',1)
從上圖我們可以清楚的看到,綠色區域的第一個8頁不屬于同個區(混合區),因為頁面號不連續,207與94752之間有缺口。接下來藍色和紅色區域是屬于同個區(統一區),因為它們的頁面號是連續的。當我們以碎片級別來看待這個情況時,可以發現表越小,碎片越高。即使你用索引重建,這個高碎片也不會減少。這個背后的原因就是SQL Server分配新的表或索引對象時,總是首先從混合區分配空間。SQL Server為新表或索引從混合區開始分配頁。一旦表增長超過8頁。SQL Server需要從統一區分配頁。當表或索引為新的或修改的數據需要更多的容納空間時,SQL Server需要這些表或索引分配頁。如果表或索引的大小小于8頁。SQL Sever需要從混合區給它們分配空間。如果大小超過8頁,SQL Server需要從統一區分配頁。SQL使用2類不同的頁來更好管理這個分配操作。
全局分配映射表(GAM: Global Allocation Map Pages) :GAM頁記錄哪些些區已被使用分配。對于每個區,GAM都有一個位。如果這個位是1,表示對應的區是空閑可用的。如果這個位是0,表示對應區被統一區或混合區使用。一個GAM頁可以保存64000個區的使用信息。這就是說,一個GAM可以保存近4G(64000 * 8 * 8/ 1024)數據文件的使用信息。簡單來說,一個7G的數據文件會有2個GAM頁。共享全局分配映射表(SGAM: Shared Global Allocation Map Pages) :SGAM頁記錄哪些區已被作為混合區使用并至少有一個可用的空閑頁。對于每個區,SGAM都有一個位。如果這個位是1,表示對應的區作為混合區使用并至少有一個可用的空閑頁。如果這個位是0,表示這個區既沒被混合區使用(作為統一區),或這個區的所有頁都作為混合區使用了。一個SGAM頁可以保存64000個區的使用信息。這就是說,一個SGAM可以保存近4G(64000 * 8 * 8/ 1024)數據文件的使用信息。簡單來說,一個7G的數據文件會有2個SGAM頁。
GAM和SGAM頁幫助數據庫引擎進行區管理。分配一個區,數據庫引擎查找標記1的GAM頁,然后標記為0。如果那個區是作為混合區分配,它會在SGAM頁把對應區的標記為1。如果那個區是作為統一區分配,那就沒有必要在SGAM里修改對應位標記。找一個有空頁的混合區,數據庫引擎在SGAM頁查找標記為1的位。如果沒找到,數據文件已經滿了。解除一個區分配,數據庫引擎會把對應GAM頁里對應位設置為1,SGAM頁里對應標記設置為0。
在每個數據文件里,第3個頁(頁號2,頁號從0開始)是GAM頁,第4個頁(頁號3,頁號從0開始)是SGAM頁。第1個頁(頁號0)是文件頭(file header),第2個頁(頁號1)是PFS(Page Free Space)頁。我們可以使用DBCC PAGE命令查看GAM和SGAM頁。
我們在AdventureWorks2008R2數據庫里驗證下:
1 USE AdventureWorks2008R22 3 DBCC TRACEON(3604)4 GO5 DBCC page('AdventureWorks2008R2',1,2,3)
輸出的結果最后一個部分:
第1行表示,在頁0到頁23112之間的區都已經被分配,也就是說頁號從0到23129的頁都被分配。
第2行表示,在頁23120到頁25072之間的區都沒被分配,也就是說頁號從22120到頁25079的頁都未被分配。
我們一起來看看分配的頁23112和未分配的頁23120在頁頭分配信息里的GAM分配情況。
1 DBCC TRACEON(3604)2 GO3 DBCC page('AdventureWorks2008R2',1,23112,1)
1 DBCC TRACEON(3604)2 GO3 DBCC page('AdventureWorks2008R2',1,23120,1)
可以看到在GAM頁的分配信息和在對應頁里頁頭的分配信息(Allocation Statu)是一致的。
我們來看看SGAM頁的分配情況:
1 DBCC TRACEON(3604)2 GO3 DBCC page('AdventureWorks2008R2',1,3,3)
第1行表示,在頁0到頁11752之間的區都已經未被分配,也就是說這些區沒被分配,或者是統一區,或者是沒有空頁的混合區,這里應該是統一區。
第2行表示,自頁11760的區開始是混合區,并且至少有1個可用的頁。
新聞熱點
疑難解答