一、基本单位“页”
SQL Server是用8KB的页来存储数据。物理I/O操作也是在页级执行。页的种类有很多,具体参考(MSDN)。我们关注更多的是数据页的结构,包括三部分:页头(96bytes)、数据区(数据行和可用空间)以及行偏移数组(槽,最少是7bytes):
为什么数据页的大小是8k,这有什么优缺点,有两篇文章解释的很好(数据页结构,坏的一面)。总结下,
a. 数据区大小 =(8192 - 页头96bytes+偏移数组7byte) = 8053bytes,这是一个页能分配给我们的数据使用的最大空间。我们的数据就一行一行的放在这写数据内部。
b. 如果我们一行数据包含两个int列,那一共可以存储 8053%(4+4)= 999.125,最后余7byte空间无法存入,也就是这这个页里浪费了7bytes。如
c. 果我们一行数据包含三列(一个int、一个char(4000)、一个char(100),共4104byte),那每个页只能存储一行,浪费了3 949bytes,很明显这不是一个好的数据库设计。
d. 可以利用free_space_in_bytes来查看页面空闲情况。
SELECT DB_NAME(database_id), SUM(free_space_in_bytes) / 1024 AS 'Free_KB' FROM sys.dm_os_buffer_descriptors WHERE database_id <> 32767 GROUP BY database_id ORDER BY SUM(free_space_in_bytes) DESC GO
e. 包含 varchar、nvarchar、varbinary 或 sql_variant 列的表不受此限制的约束。MSDN上有进一步解释行溢出数据超过 8 KB。
f. 要进一步了解数据页内部的结构,参考:http://www.cnblogs.com/woodytu/p/4484328.html
二、页的上层--“区”和分配映射表
区是管理空间的基本单位。一个区是八个物理上连续的页(即 64 KB)。这意味着 SQL Server 数据库中每 MB 有 16 个区。
由于历史原因,SQL Serve有两种类型的区:同一区、混合区。
混合区:区内的8个页,可以是不同的表、索引等。
统一区:区内的8个页,是同一个表、索引。
新建表的时候,先在混合区插入一条记录,当其占用的这个混合区的表或索引增长到 8 页时,将变成使用统一区进行后续分配,每次扩展84kb(8页)。问题是如何管理这两种分区?答案是GAM页和SGAM页。
1. 全局分配映射表(GAM: Global Allocation Map Pages)---为统一区管理服务
这是一个页,共64000位(8000bytes)的掩码位图(参考位图算法),用一个位管理一个byte管理4Gbyte。所以每隔4G的数据文件都要有一个GAM页进行管理(64000 * 64 /1024 /1024)。
2. 共享全局分配映射表(SGAM: Shared Global Allocation Map Pages)---为混合区管理服务
原理同全局分配映射表。
三、可用空间管理页面:PFS页(Page Free Space)
该页面用来跟踪一个文件中每一个特定的页面的利用率情况,是以页为单位的。一个文件中第二个页面(页码1,如下图)就是PFS页面,该页面的每个字节都记录了相应页面的分配情况、页面类型、是否IAM页、是否包含删除记录、以及空间利用率信息;PFS能够管理和跟踪8088个页面的使用情况,即接近64M的空间,以后每8088个页面将再出现一次(参考)。
PFS每个字节管理一个页面,字节结构为:
四、索引分配映射页:IAM页
主要用来标示 SQL Server 对象使用了哪些区。比如A表的非聚集索引B占用了 6、7、8、9 这4个区。这样,在再对此对象做更改的时候,能够快速的找到这4个区,更改文件。
当 SQL Server 数据库引擎必须在当前页中插入新行,而当前页中没有可用空间时,它将使用 IAM 和 PFS 页查找要将该行分配到的页,或者(对于堆或 Text/Image 页)查找具有足够空间容纳该行的页。分配的过程是:
1. 数据库引擎使用 IAM 页查找分配给分配单元的区。
2. 对于每个区,数据库引擎将搜索 PFS 页,以查看是否有可用的页。
每个 IAM 和 PFS 页覆盖大量数据页,因此一个数据库内只有很少的 IAM 和 PFS 页。这意味着 IAM 和 PFS 页通常位于内存中的 SQL Server 缓冲池中,所以能够很快找到它们。对于索引,新行的插入点由索引键设置。在这种情况下,不会出现上述搜索过程。
另外,一个 IAM 页可以映射的范围 4 GB,与 GAM 或 SGAM 页的范围相同。如果分配单元包含来自多个文件的区,或者超过一个文件的 4 GB 范围,那么一个 IAM 链中将链接多个 IAM 页。
五、已修改区域的管理(参考MSDN)
SQL Server 使用两个内部数据结构跟踪被大容量复制操作修改的区,以及自上次完整备份后修改的区。这些数据结构极大地加快了差异备份的速度。当数据库使用大容量日志恢复模式时,这些数据结构也可以加快将大容量复制操作记录至日志的速度。与全局分配图 (GAM) 和共享全局分配图 (SGAM) 页相同,这些结构也是位图,其中的每一位代表一个单独的区。 包括
1. 差异更改映射表 (DCM)
2. 大容量更改映射表 (BCM)
DCM 页和 BCM 页的间隔与 GAM 和 SGAM 页的间隔相同,都是 64,000 个区。在物理文件中,DCM 和 BCM 页位于 GAM 和 SGAM 页之后。
六、总结
通过以上介绍,我们大体知道了SQL Server物理文件的结构:
有一篇更深入的介绍http://www.cnblogs.com/woodytu/p/4495021.html
参考:索引概念分类:https://technet.microsoft.com/zh-cn/library/ms175049(v=sql.105).aspx
聚集索引结构:https://technet.microsoft.com/zh-cn/library/ms177443(v=sql.105).aspx