SQLServer基础之数据页类型:GAM,SGAM,PFS
简介
我们已经知道SQL Server IO最小的单位是页,连续的8个页是一个区。SQL Server需要一种方式来知道其所管辖的数据库中的空间使用情况,这就是GAM页和SGAM页。
GAM页
GAM(全局分配位图)是用于标识SQL Server空间使用的位图的页。位于数据库的第3个页,也就是页号是2的页。下面我们通过新建一个数据库来看其GAM的结构。创建测试数据库的代码如代码所示。
CREATE DATABASE [test] ON PRIMARY
( NAME = N'test', FILENAME = N'C:\Test\test.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'test_log', FILENAME = N'C:\Test\test_log.ldf' , SIZE = 2048KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
代码1.创建测试数据库
数据库创建成功后,通过查看数据库页号为2的页。我们看到如图1所示的结果。

图1.GAM页示例
我们看到页内的数据通过16进制表示。也就是一个数字是4比特,两个是一字节。其中前4个字节0000381f是系统信息,slot1的后10个字节也是系统信息。其余的每位表示SQL Server的一个区的状态,0表示已分配,1表示未分配。下面我们就通过图1所示的GAM页来计算一下这个数据库所占的空间。
我们可以看到,由于数据库刚刚创建,分配的空间在第4-8个字节就能表示,也就是0001c0ff。下面将0001c0ff由16进制化为2进制。结果是
0000 0000 0000 0001 1100 0000 1111 1111
通过计算,可以看出,上面的bit中有21个0,也就是目前数据库已经分配了21个区,我们知道每个区是8*8k=64K。因此算出这个数据库占用空间(21*64)/1024=1.3125MB≈1.31MB
下面我们通过SSMS来看数据库实际占用的空间,如图2所示。

图2.通过SSMS来看数据库所占的空间
通过上面的计算3-1.69=1.31MB和通过GAM页进行计算的结果完全吻合。
那可能大家会有疑问了,那如果数据库增长超过一个GAM所能表示的区的范围那该怎么办?答案很简单,就是再创建一个GAM页,第二个GAM页的位置也可以通过图1中的信息进行计算。图1中slot1有7992个字节,其中前四个字节用于存储系统信息,后面7988字节用于表示区的情况,因此所能表示的区是7988*8=63904,横跨的页的范围是511232,所以第511232+1页应该是下一个GAM页,而页号就会是511232页。这个区间也就是所谓的GAM Interval,接近4GB。
SGAM页
通过GAM页可知,分配空间的最小单位是区。但假如一个非常小的索引或是表只占1KB,但要分给其64K的空间就显得过于奢侈了。所以当几个表或索引都很小时,可以让几个表或索引公用一个区,这类区就是混合区。而只能让一个表或索引使用的区就是统一区。SGAM位于数据库的第四页,也就是GAM的下一个页。页号为3。通过和GAM相同位置的bit组合,就能知道空间的状态。所能表示的几种状态如表1所示。
| GAM | SGAM位 | |
| 未分配 | 1 | 0 |
| 统一区或空间使用完的混合区 | 0 | 0 |
| 含有可分配空间的混合区 | 0 | 1 |
表1.SGAM和GAM
通过SGAM和GAM的组合,SQL Server就能知道该从哪里分配空间。
第二个SGAM页位于第二个GAM页之后,也就是页号为511233的页。依此类推。
PFS页
PFS表示页可用空间。但是PFS页跟踪的远不止这些。和GAM区间相似,每个数据库文件同样也被分割成(概念上)PFS区间。一个PFS区间是8088页或约64MB。PFS页中不是位图,它是字节图,每个字节表示PFS区间中的一页(不包括PFS页本身)。
字节中每位的含义如下:
1)位0-2:页中有多少可用空间
a)0x00表示空
b)0x01表示1~50%满
c)0x02表示51~80%满
d)0x03表示81~95%满
e)0x04表示96~100%满
2)位3(0x08):页中是否至少有一个ghost记录?
3)位4(0x10):是否为IAM页?
4)位5(0x20):是否为混合页?
5)位6(0x40):页是否已分配?(分配状态位)
比如一个IAM页的PFS字节为0x70(已分配 + IAM页 + 混合页)。你可以使用DBCC PAGE来查看PFS页。
跟踪可用空间只适用于存储LOB值(比如SQL SERVER 2000中的text/image类型;SQL SERVER 2005中再加上varchar(max)/varbinary(max)/XML类型以及行溢出数据)和堆数据页。因为只有这些页存储的数据不用排序,所以可以在任何位置插入。而像索引是有明确的顺序的,所以插入点是没有选择的。
重置PFS字节不是很直观的。如果一个PFS字节为0x04的页,它是如何做到既满而又没有分配的?
答案是:(页释放时)PFS字节不会全部重置,直到该页被重新分配。在页被释放时,PFS字节中只有1位会变化——分配状态位,这样要是回滚的话就很简单了。
IAM页
索引分配映射(Index Allocation Map,IAM)页面我们将在下一篇中详细介绍IAM页。
SQLServer基础之数据页类型:GAM,SGAM,PFS的更多相关文章
- SQL SERVER大话存储结构(1)_数据页类型及页面指令分析
如果转载,请注明博文来源: www.cnblogs.com/xinysu/ ,版权归 博客园 苏家小萝卜 所有.望各位支持! SQLServer的数据页大 ...
- SQL Server 存储(1/8):理解数据页结构
我们都很清楚SQL Server用8KB 的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行.也就是说,SQL Server 读取或写入所有数据页.页有不同的类型,像数据页,GA ...
- SQL Server :理解数据页结构
原文:SQL Server :理解数据页结构 我们都很清楚SQL Server用8KB 的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行.也就是说,SQL Server 读取或 ...
- DBCC page 数据页 堆 底层数据分布大小计算
1.行的总大小: Row_Size = Fixed_Data_Size + Variable_Data_Size + Null_Bitmap + 4(4是指行标题开销) 开销定义: Fixed_Dat ...
- 06006_redis数据存储类型——String
1.概述 (1)字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这意味着该类型可以接受任何格式的数据,如JPEG图像数据或Json对象描述信息等: (2)在Redis中 ...
- 直接在安装了redis的Linux机器上操作redis数据存储类型--String类型
一.概述: 字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据或Json对象描述信息等.在Redis中字符串类型 ...
- 已经不再使用的表为什么数据页还在SQLServer的内存缓存中
1. 问题发现 在学习内存调优时,使用如下代码,查询目前内存缓冲区中生产数据库的每个对象缓存页计数 SELECT count(*)AS cached_pages_count ,name ,index_ ...
- [SqlServer] 理解数据库中的数据页结构
这边文章,我将会带你深入分析数据库中 数据页 的结构.通过这篇文章的学习,你将掌握如下知识点: 1. 查看一个 表/索引 占用了多少了页. 2. 查看某一页中存储了什么的数据. 3. 验证在数据库中用 ...
- 读写SQLServer数据库中的image类型数据(简单)
1.将double类型的数据存储于image类型的变量中: (1). char *CManualForecastResultBll::DoubleArray2Binary(std::vector< ...
随机推荐
- linux 命令 — split
split 按照数据大小和行数来分割文件 指定分割文件后缀 split -b 10k data.file 按照每个文件10k分割文件(默认使用字母作为后缀) split -b 10k data.fil ...
- SOAP报文转成JAVA对象
在今天以前我还没有用过代码解析过SOAP报文,更别提转成JAVA对象了,今天的任务中报文这个模样的,(为防止数据信息,以下数据我故意打乱了防止泄露什么信息.) <?xml version=&qu ...
- Go Web:数据存储(3)——gob对象序列化
序列化持久存储gob 1.内存存储 2.CSV文件存储 3.gob序列化存储 本篇文章仍然接前面的文章:内存存储,主要介绍将博客文章数据序列化持久到文件中. encoding/gob包用于编码器和解码 ...
- [转]Laravel 数据库实例教程 —— 使用查询构建器实现对数据库的高级查询
本文转自:https://laravelacademy.org/post/920.html 上一节我们简单介绍了如何使用查询构建器对数据库进行基本的增删改查操作,这一节我们来探讨如何使用查询构建器实现 ...
- JQuery官方学习资料(译):$ vs $()
直到现在,我们一直是通过一个jQuery对象来调用函数的,例如: $( "h1" ).remove(); 大多数jQuery函数是通过jQuery对象调用的,这是$.fn ...
- 【Linux命令】top命令
一.简介 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,常用于服务端性能分析. 二.使用 1.查看进程内线程情况 top -Hp 2556(2556为进程号)找 ...
- Spring 与 SpringMVC (或许不完整)
一.什么是Spring Spring是一个开源的控制反转和面向切面(AOP)的容器框架.它的主要目的是使现有技术更加易用,推荐编码最佳实现,从而简化企业的开发. 提:使用Spring的好处有以下几项: ...
- 修改CentOS服务器时间为北京时间
购买了VPS,CentOS系统,发现服务器时间与北京时间往往不一致,存在时差. [clive@server workspace]$ date 2018年 05月 30日 星期三 02:02:47 UT ...
- 一些你可能不熟悉的JS知识点总结
js代码暂时性死区 只要块级作用域存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响.这么说可能有些抽象,举个例子: ? 1 2 3 4 5 var temp = 123; if(tr ...
- 实现响应式——CSS变量
CSS 变量是 CSS 引入的一个新特性,目前绝大多数浏览器已经支持了,它可以帮助我们用更少的代码写出同样多的样式,大大提高了工作效率,本篇文章将教你如何使用 CSS 变量(css variable) ...