SQL Server 存储(3/8):理解GAM和SGAM页
我们知道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查看这个表的相关页面:
USE InternalStorageFormat
GO IF EXISTS ( SELECT *
FROM sysobjects
WHERE id = OBJECT_ID(N'[dbo].[TestSpaceAllocation]')
AND OBJECTPROPERTY(id, N'IsUserTable') = 1 )
DROP TABLE dbo.TestSpaceAllocation CREATE TABLE TestSpaceAllocation(
Name CHAR(8000)
)
GO INSERT INTO TestSpaceAllocation VALUES('Woody')
GO 26 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数据库里验证下:
USE AdventureWorks2008R2 DBCC TRACEON(3604)
GO
DBCC page('AdventureWorks2008R2',1,2,3)
输出的结果最后一个部分:

第1行表示,在页0到页23112之间的区都已经被分配,也就是说页号从0到23129的页都被分配。
第2行表示,在页23120到页25072之间的区都没被分配,也就是说页号从22120到页25079的页都未被分配。
我们一起来看看分配的页23112和未分配的页23120在页头分配信息里的GAM分配情况。
DBCC TRACEON(3604)
GO
DBCC page('AdventureWorks2008R2',1,23112,1)

DBCC TRACEON(3604)
GO
DBCC page('AdventureWorks2008R2',1,23120,1)

可以看到在GAM页的分配信息和在对应页里页头的分配信息(Allocation Statu)是一致的。
我们来看看SGAM页的分配情况:
DBCC TRACEON(3604)
GO
DBCC page('AdventureWorks2008R2',1,3,3)

第1行表示,在页0到页11752之间的区都已经未被分配,也就是说这些区没被分配,或者是统一区,或者是没有空页的混合区,这里应该是统一区。
第2行表示,自页11760的区开始是混合区,并且至少有1个可用的页。
参考文章:
SQL Server 存储(3/8):理解GAM和SGAM页的更多相关文章
- SQL Server :理解GAM和SGAM页
原文:SQL Server :理解GAM和SGAM页 我们知道SQL Server在8K 的页里存储数据.分区就是物理上连续的8个页.当我们创建一个数据库,数据文件会被逻辑分为页和区,当用户对象创建时 ...
- SQL Server 存储(8/8):理解数据文件结构
这段时间谈了很多页,现在我们可以看下这些页在数据文件里是如何组织的. 我们都已经知道,SQL Server把数据文件分成8k的页,页是IO的最小操作单位.SQL Server把数据文件里的第1页标记为 ...
- SQL Server 存储(5/8):理解IAM 页
在以前的文章里,我们讨论了数据页,GAM和SGAM,还有PFS页.今天我们一起来讨论下索引分配映射(Index Allocation Map:IAM)页. 在SQL Server 2005和以后的版本 ...
- SQL Server存储(6/8) :理解DCM页
我们已经讨论了各种不同的页,包括数据页.GAM与SGAM页.PFS页,还有IAM页.今天我们来看下差异变更页(Differential Change Map:DCM ),还有差异备份(differen ...
- SQL Server存储(7/8) :理解BCM页
今天我们来讨论下批量更改映射(Bulk Changed Map:BCM)页,还有大容量日志恢复模式( bulk logged recovery model )如何运作的. 批量更改映射(Bulk Ch ...
- SQL Server 存储(4/8):理解Page Free Space (PFS) 页
我们已经讨论了GAM与SGAM页,数据页(Data Page) ,现在我们来看下页面自由空间页(Page Free Space (PFS) ). PFS在数据文件里是第2页(页号1,页号从0开始),接 ...
- SQL SERVER存储引擎——04.数据
4. SQL SERVER存储引擎之数据篇 (4.1)文件 (0)主数据文件.mdf初始文件大小至少为3MB,次要数据文件.ndf初始大小,同日志文件一样至少为512KB: (1)SQL SERVER ...
- SQL Server存储ntext截断问题
SQL Server存储ntext截断问题 最近遇到一个问题:将大文本存储到数据库的时候,查询出来的文本却被截断了. 最后百度发现,作者提出 sql server management studi ...
- SQL Server分页语句ROW_NUMBER,读取第4页数据,每页10条
SQL Server分页语句ROW_NUMBER,读取第4页数据,每页10条 SELECT Id,[Title],[Content],[Image] FROM ( SELECT ROW_NUMBER( ...
随机推荐
- vmware安装linux6.3
安装信息: 1.vmware9.0下载地址:http://pan.baidu.com/share/link?shareid=1287299796&uk=2585121485 2.oraclel ...
- 激活神器 KMSAuto Net 2015 v1.3.8
KMSAuto Net – Windows 操作系统 KMS 自动激活工具!支持 Windows Vista,7,8,8.1,10, Server 2008,2008 R2,2012,2012 R2, ...
- Linux进程管理、任务管理
查看进程 Linux中的进程可以使用ps.pstree命令查看. 一般使用 ps aux (注意,没有短划线-:虽然加上不影响执行,只是会提示),还可以使用 ps -le,都是查看所有进程,区别在于显 ...
- android 很多牛叉布局github地址(转)
原文地址 http://blog.csdn.net/luo15309823081/article/details/41449929 点击可到达github-------https://github.c ...
- Winform中Grid跨行复制一列
Private Sub DataCopyToGrid() '判断剪切板中是否存在内容 If Clipboard.ContainsText Then Dim str = Clipboard.GetTex ...
- OpenResty(nginx_lua_module)做ES代理以及备份ES数据
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...
- Spring In action chapter1_wiringBeans
Automatically wiring beans Spring attacks automatic wiring from two angles: Component scanning-Sprin ...
- CodeForces 742A Arpa’s hard exam and Mehrdad’s naive cheat
题意:求1378 n次幂的最后一位. 析:两种方法,第一种,就是快速幂,第二种找循环节,也很好找,求一下前几个数就好. 代码如下: #pragma comment(linker, "/STA ...
- Clover 资源管理器 http://cn.ejie.me/
附件列表 clover.jpg
- 《转》python线程池
线程池的概念是什么? 在IBM文档库中这样的一段描写:“在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是 如此,虚拟机将试图跟踪每一个对象 ...