SQL Server 数据文件存储结构
一、数据库文件
1、数据库文件的类型
(1)mdf(主数据文件)。这个文件保存着数据库的数据,是数据库的起点,指向数据库中的其他文件。每个数据库必须有一个mdf,而且只能有一个。
(2)ndf(次要数据文件)。这个文件也用于保存数据库的数据,除了mdf以外的所有其他数据文件都是ndf。每个数据库可能没有ndf,也可能有多个ndf。
(3)ldf文件。这个文件保存着数据库的日志数据,包含了用于恢复数据库的所有日志信息。每个数据库默认只有一个ldf,可以添加多个(不推荐)。
SQL Server 不强制使用上述文件扩展名。建议参照上述规范使用文件扩展名,有助于识别每个文件的类型与用途。
2、储存的文件信息
数据库中所有文件的名称、位置等信息都保存在该数据库的mdf以及master数据库中。大多数情况下,数据库引擎使用master数据库中的信息。但是,以下情况时使用mdf的信息来初始化master数据库的相关项:
(1)附加(attach)数据库时。
(2)从SQL Server 7.0/2000进行升级时。
(3)还原master数据库时。
3、组织结构
(1)文件组(File Group)
为了便于分配和管理,可以将数据库的数据文件分成文件组。每个数据库默认有一个“主文件组”,它包含了mdf和任何没有明确分配给其他文件组的其他文件,也包含了该数据库中的所有系统表。
db_owner数据库角色成员可以将默认的文件组从一个文件组切换到另一个。如果没有指定默认文件组,则将主文件组设为默认文件组。
创建表和索引时,如果没有指定文件组,则在默认文件组中为其分配页。可以在Create Table和Create Index语句中使用On FilGroup关键字指定文件组。
FileStream文件组是特殊的文件组,它的文件实际上是指向一个物理文件夹。
(2)HOBT
表使用堆(Heap)或聚集索引组织数据页。聚集表是有聚集索引的表,数据行基于聚集索引键按顺序存储,聚集索引键按B树索引结构实现。堆是没有聚集索引的表,数据行不按任何特殊的顺序存储,数据页也没有任何特殊的顺序。
由于table的数据行存储方式不是堆就是B树,因此被称为Heap Or Balance Tree。
3、物理结构
表包含在一个或多个分区中,每个分区在一个HOBT结构包含数据行,HOBT在一个或多个分配单元(IN_ROW_DATA、LOB_DATA、ROW_OVERFLOW_DATA)中进行管理。表的结构如下图:
(1)分区
SQL Server 2005引入了分区的概念。当表或索引使用分区时,数据将被水平分割成多个单元,根据指定的列将行组映射到各个分区。
对分区中的数据进行查询或更新时,表或索引对象将被视为单个逻辑实体。
(2)数据文件
每个文件组可以包含一个或多个数据文件(mdf或ndf)。同一个文件组里的文件是均衡存储的。 例如,一个文件组有3个文件,大小分别为1GB、2GB、3GB,如果累计往这个文件组里写入600MB的数据,则分别向3个文件写入100MB、200MB、300MB。
四、堆与索引
1、堆的表扫描或串行读
可以通过扫描 IAM 页对堆进行表扫描或串行读操作来找到容纳该堆的页的区。
2、聚集索引
在 SQL Server 中,索引是按 B 树结构进行组织的。索引 B 树中的每一页称为一个索引节点。B 树的顶端节点称为根节点。索引中的底层节点称为叶节点。根节点与叶节点之间的任何索引级别统称为中间级。
在聚集索引中,叶节点包含基础表的数据页。根节点和中间级节点包含存有索引行的索引页。每个索引行包含一个键值和一个指针,该指针指向 B 树上的某一中间级页或叶级索引中的某个数据行。每级索引中的页均被链接在双向链接列表中。
当聚集索引有多个分区时,每个分区都有一个包含该特定分区相关数据的 B 树结构。例如,如果聚集索引有4个分区,就有4个 B 树结构,每个分区中有一个 B 树结构。
3、非聚集索引
非聚集索引中的每个索引行都包含非聚集键值和行定位符。此定位符指向聚集索引或堆中包含该键值的数据行。
非聚集索引行中的行定位器为以下两种之一:
(1)如果表是堆(意味着该表没有聚集索引),则行定位器(row locator)是指向行的指针。该指针由文件标识符(file ID)、页码(page number)和页上的行数(number of the row on the page)生成。整个指针称为行 ID (RID)。
(2)如果表有聚集索引或索引视图上有聚集索引,则行定位器是行的聚集索引键。如果聚集索引不是唯一的索引,SQL Server 将添加在内部生成的值(称为唯一值)以使所有重复键唯一。此四字节的值对于用户不可见。仅当需要使聚集键唯一以用于非聚集索引中时,才添加该值。SQL Server 通过使用存储在非聚集索引的叶行内的聚集索引键搜索聚集索引来检索数据行。
4、堆上的非聚集索引
当使用非聚集索引查找一条记录时,数据库引擎将遍历B树直到找到该记录的索引值。然后使用RID,直接找到数据页上的数据。
RID从来不会被更新,因为当数据存储在堆上时,数据的定位从来不会变化。当某row被更新并且不再放在原始的页上,将储存一个页向后指针(page forwarded pointer)来查找该行。
当一个查询所请求的列不包括在索引中,将使用RID lookup。
5、聚集索引上的非聚集索引
例如,一个查询要求按2列进行查找某条记录。数据库引擎首先遍历了非聚集索引直到找到符合第1列的索引值,然后第2列所在的索引页包含了聚集索引,那么数据库引擎将遍历聚集索引以找到符合第2列的索引值所在的数据行。