SQL Server的逻辑存储结构为文件组(file group)、区(extent)、数据页(data page)。
SQL Server 将数据库映射为一组操作系统文件。数据和日志信息绝不混合在同一个文件中,而且一个文件只由一个数据库使用。文件组是文件的命名集合,用于简化数据存放和管理任务(例如,备份和还原操作)。
数据库文件
SQL Server 数据库具有三种类型的文件:
- 主数据文件
主数据文件是数据库的起点。除了存储系统以及用户数据以外,主数据文件还存储了数据库中的所有辅助数据文件以及重做日志文件的路径、名称、大小等信息。SQL Server通过读取主数据文件得到其他数据文件及重做日志文件的信息,这个功能与Oracle控制文件相似。每个数据库都有一个主数据文件。主数据文件的推荐文件扩展名是 .mdf。 - 次要数据文件
除主数据文件以外的所有其他数据文件都是次要数据文件,次数据文件一般只存储用户数据。某些数据库可能不含有任何次要数据文件,而有些数据库则含有多个次要数据文件。次要数据文件的推荐文件扩展名是 .ndf。 - 日志文件
日志文件包含着用于恢复数据库的所有日志信息。每个数据库必须至少有一个日志文件,当然也可以有多个。日志文件的推荐文件扩展名是 .ldf。
SQL Server 不强制使用 .mdf、.ndf 和 .ldf 文件扩展名,但使用它们有助于标识文件的各种类型和用途。
在 SQL Server 中,数据库中所有文件的位置都记录在数据库的主文件和 master 数据库中。大多数情况下,SQL Server 数据库引擎使用 master 数据库中的文件位置信息。但是,在下列情况下,数据库引擎使用主文件的文件位置信息初始化 master 数据库中的文件位置项:
- 使用带有 FOR ATTACH 或 FOR ATTACH_REBUILD_LOG 选项的 CREATE DATABASE 语句来附加数据库时。
- 从 SQL Server 2000 版或 7.0 版升级时。
- 还原 master 数据库时。
数据库文件组
为便于分配和管理,可以将数据库对象和文件一起分成文件组。SQL Server的文件组由若干个数据文件组成。
SQL Server的文件组分为primary文件组和用户文件组,分别对应Oracle数据库中的system表空间和用户表空间。
- primary文件组
主文件组包含主数据文件和任何没有明确分配给其他文件组的其他文件。系统表的所有页均分配在主文件组中。与Oracle数据库的system表空间相似,primary文件组不能删除,其名称primary也是固定不能修改的。 - 用户定义文件组
用户定义文件组是通过在 CREATE DATABASE 或 ALTER DATABASE 语句中使用 FILEGROUP 关键字指定的任何文件组。
日志文件不包括在文件组内。日志空间与数据空间分开管理。
SQL Server数据库中没有对应于Oracle临时表空间的文件组,SQL Server的多版本数据(undo)以及排序或散列操作所产生的临时数据都存储于tempdb系统数据库中,多个数据库共用tempdb数据库。
一个文件不可以是多个文件组的成员。表、索引和大型对象数据可以与指定的文件组相关联。在这种情况下,它们的所有页将被分配到该文件组,或者对表和索引进行分区。已分区表和索引的数据被分割为单元,每个单元可以放置在数据库中的单独文件组中。
在 SQL Server数据库中,不允许删除包含表或索引的文件组,这与Oracle不同,在Oracle中,如果表空间中包含数据,使用drop tablespace删除表空间时,可以附加including contents子句。
每个数据库中均有一个文件组被指定为默认文件组。如果创建表或索引时未指定文件组,则将假定所有页都从默认文件组分配。一次只能有一个文件组作为默认文件组。如果没有指定默认文件组,则将主文件组作为默认文件组。db_owner 固定数据库角色成员可以将默认文件组从一个文件组切换到另一个。
文件和文件组的设计规则
下列规则适用于文件和文件组:
- 一个文件或文件组不能由多个数据库使用。例如,任何其他数据库都不能使用包含 sales 数据库中的数据和对象的文件 sales.mdf 和 sales.ndf。
- 一个文件只能是一个文件组的成员。
- 事务日志文件不能属于任何文件组。
区(extent)
extent是给表或索引分配存储空间的单位,也是管理空间的基本单位。
在SQL Server中,extent的大小是固定的8个连续的数据页,64KB,这意味着 SQL Server 数据库中每 MB 有 16 个区。在创建文件组时,不能指定类似Oracle中的autoallocate或uniform size子句定义extent的大小,在这方面,SQL Server的灵活性稍差一些。
SQL Server对表的分配extent的方式与Oracle不同。为了使空间分配有效,SQL Server 不会将所有区分配给包含少量数据的表,所以SQL Server不会对空表分配extent,extend的分配会延迟到对表添加记录时。
SQL Server 有两种类型的区:
- 混合区(mixed extent):混合区由多个表或索引共用,最多可由八个对象共享。 区中八页的每页可由不同的对象所有。
- 统一区(uniform extent):统一区由由单个对象所有。区中的所有 8 页只能由一个表或索引专用。
通常对表或索引分配的前8个数据页会在混合区内分配,以后的数据页则在统一区内分配,这种方式与Oracle不同,Oracle的一个区只能分配给一个表或索引,不能多个对象共用,或者也可以说,Oracle只有SQL Server中的统一区一种类型。
页(data page)
SQL Server 中数据存储的基本单位是页。 为数据库中的数据文件(.mdf 或 .ndf)分配的磁盘空间可以从逻辑上划分成页(从 0 到 n 连续编号)。 磁盘 I/O 操作在页级执行。 也就是说,页也是也是读写数据的单位。
页是区段的分配单元。每一个区段包含8个页,每个页的大小固定为8KB,不能修改,这与Oracle数据库在创建表空间时可以指定数据库大小不同。
上图展示了数据是如何存放在页中的。对于插入的每一行,为了表明特定行的数据开始于页中的何处,每一页的末尾都用一小块空间记录的每一行相对于页头位置的偏移量。
SQL Server 数据文件中的页按顺序编号,文件的首页以 0 开始。数据库中的每个文件都有一个唯一的文件 ID 号。若要唯一标识数据库中的页,需要同时使用文件 ID 和页码。
管理SQL Server文件组及文件组
ALTER DATABASE database_name
{
<add_or_modify_files>
| <add_or_modify_filegroups>
}
[;]
<add_or_modify_files>::=
{
ADD FILE <filespec> [ ,...n ]
[ TO FILEGROUP { filegroup_name } ]
| ADD LOG FILE <filespec> [ ,...n ]
| REMOVE FILE logical_file_name
| MODIFY FILE <filespec>
}
<filespec>::=
(
NAME = logical_file_name
[ , NEWNAME = new_logical_name ]
[ , FILENAME ={'os_file_name'|'filestream_path'|'memory_optimized_data_path'}]
[ , SIZE = size [ KB | MB | GB | TB ] ]
[ , MAXSIZE = { max_size [ KB | MB | GB | TB ] | UNLIMITED } ]
[ , FILEGROWTH = growth_increment [ KB | MB | GB | TB| % ] ]
[ , OFFLINE ]
)
<add_or_modify_filegroups>::=
{
| ADD FILEGROUP filegroup_name
[ CONTAINS FILESTREAM | CONTAINS MEMORY_OPTIMIZED_DATA ]
| REMOVE FILEGROUP filegroup_name
| MODIFY FILEGROUP filegroup_name
{ <filegroup_updatability_option>
| DEFAULT
| NAME = new_filegroup_name
| { AUTOGROW_SINGLE_FILE | AUTOGROW_ALL_FILES }
}
}
<filegroup_updatability_option>::=
{
{ READONLY | READWRITE } | { READ_ONLY | READ_WRITE }
}
- <add_or_modify_files>::=</add_or_modify_files>:指定要添加、删除或修改的文件。
- database_name:要修改的数据库的名称。
- ADD FILE:向数据库中添加文件。
- TO FILEGROUP { filegroup_name }:指定要将指定文件添加到的文件组。
- ADD LOG FILE:将要添加的日志文件添加到指定的数据库。
- REMOVE FILE logical_file_name:从 SQL Server 的实例中删除逻辑文件说明并删除物理文件。 除非文件为空,否则无法删除文件。
- logical_file_name:在 SQL Server 中引用文件时所用的逻辑名称。
- MODIFY FILE:指定应修改的文件。 如果指定了 SIZE,那么新大小必须比文件当前大小要大。
若要修改数据文件或日志文件的逻辑名称,请在 NAME 子句中指定要重命名的逻辑文件名称,并在 NEWNAME 子句中指定文件的新逻辑名称。 例如:
MODIFY FILE ( NAME = logical_file_name, NEWNAME = new_logical_name )
若要将数据文件或日志文件移至新位置,请在 NAME 子句中指定当前的逻辑文件名称,并在 FILENAME 子句中指定新路径和操作系统(物理)文件名称。 例如:
MODIFY FILE ( NAME = logical_file_name, FILENAME = ' new_path/os_file_name ')
- { 'os_file_name' | 'filestream_path' | 'memory_optimized_data_path'}
- os_file_name:对于标准 (ROWS) 文件组,这是在创建文件时操作系统所使用的路径和文件名。
- ' filestream_path ':对于 FILESTREAM 文件组,FILENAME 指向将存储 FILESTREAM 数据的路径。
- memory_optimized_data_path:对于内存优化文件组,FILENAME 会引用将存储内存优化数据的路径。SIZE、MAXSIZE 和 FILEGROWTH 属性不适用于内存优化文件组。
- FILEGROWTH:用于指定每次文件增长大小,如果未指定确定的值,则默认为1MB,如果指定为0,则数据文件不能自动增长。可以使用MB、KB、GB、TB或百分比(%)为单位,默认值为MB。如果指定%,则增量大小为发生增长时文件大小的指定百分比。指定的大小舍入为最接近64KB的倍数。
- OFFLINE:将文件设置为脱机并使文件组中的所有对象都不可访问。
- <add_or_modify_filegroups>::=</add_or_modify_filegroups>:在数据库中添加、修改或删除文件组。
- CONTAINS FILESTREAM:指定文件组在文件系统中存储 FILESTREAM 二进制大型对象 (BLOB)。
- CONTAINS MEMORY_OPTIMIZED_DATA:指定文件组在文件系统中存储内存优化数据。每个数据库只能有一个 MEMORY_OPTIMIZED_DATA 文件组。 在创建内存优化表时,文件组不能为空,其中必须至少包含一个文件。
- REMOVE FILEGROUP filegroup_name:删除文件组filegroup_name从数据库中删除文件组。 除非文件组为空,否则无法将其删除。 首先从文件组中删除所有文件。
- MODIFY FILEGROUP filegroup_name:修改文件组。
- DEFAULT:更改默认的数据库文件组到filegroup_name。 数据库中只能有一个文件组作为默认文件组。
- AUTOGROW_SINGLE_FILE:在文件组中的文件符合自动增长阈值时,仅该文件是增长。 这是默认设置。
- AUTOGROW_ALL_FILES:如果文件组中的文件达到了自动增长阈值,文件组中的所有文件都增长。
- <filegroup_updatability_option>:对文件组设置只读或读/写属性。
- READ_ONLY | READONLY:指定文件组为只读。 不允许更新其中的对象。 主文件组不能设置为只读。 若要更改此状态,您必须对数据库有独占访问权限。
- 因为只读数据库不允许数据修改,所以将发生以下情况:
系统启动时,将跳过自动恢复。
不能收缩数据库。
在只读数据库中不会进行锁定。 这可以加快查询速度。
【示例】
A. 向数据库中添加由两个文件组成的文件组
以下示例在 AdventureWorks2012 数据库中创建文件组 Test1FG1,然后将两个 5 MB 的文件添加到该文件组。
USE master
ALTER DATABASE AdventureWorks2012
ADD FILEGROUP Test1FG1;
GO
ALTER DATABASE AdventureWorks2012
ADD FILE
(
NAME = test1dat3,
FILENAME = 'D:\Microsoft SQL Server\MSSQL\DATA\t1dat3.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
),
(
NAME = test1dat4,
FILENAME = 'D:\Microsoft SQL Server\MSSQL\DATA\t1dat4.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
)
TO FILEGROUP Test1FG1;
GO
B.向数据库中添加两个日志文件
USE master;
ALTER DATABASE AdventureWorks2012
ADD LOG FILE
(
NAME = test1log2,
FILENAME = 'D:\Microsoft SQL Server\MSSQL\DATA\test2log.ldf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
),
(
NAME = test1log3,
FILENAME = 'D:\Microsoft SQL Server\DATA\test3log.ldf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB
);
GO
C.从数据库中删除文件
USE master;
ALTER DATABASE AdventureWorks2012
REMOVE FILE test1dat4;
GO
D.修改文件
以下示例添加的一个文件的大小。ALTER DATABASE MODIFY FILE 命令与可以使文件大小更大,因此如果你需要使文件大小更小你需要使用 DBCC SHRINKFILE。
USE master;
ALTER DATABASE AdventureWorks2012
MODIFY FILE
(NAME = test1dat3,
SIZE = 200MB);
GO
此示例中收缩数据文件的大小为 100 MB,然后指定在该数量的大小。
USE AdventureWorks2012;
DBCC SHRINKFILE (AdventureWorks2012_data, 100);
GO
USE master;
ALTER DATABASE AdventureWorks2012
MODIFY FILE
(NAME = test1dat3,
SIZE = 200MB);
GO
E.将文件移至新位置
下面以把AdventureWorks数据中的数据文件E:\t1dat2.ndf移动到C:\t1dat2.ndf为例,说明移动数据文件的过程。
首先把数据库脱机:
alter database AdventureWorks set offline
在操作系统中把E:\t1dat2.ndf移动到C:\t1dat2.ndf:
!! move E:\t1dat2.ndf C:\t1dat2.ndf
修改数据库中对此文件路径的记载:
ALTER DATABASE AdventureWorks
MODIFY FILE
(
NAME = Test1dat2,
FILENAME = N'C:\t1dat2.ndf'
);
GO
最后再把数据库重新联机:
alter database AdventureWorks set online
然后查询t1dat2的物理文件路径:
select name,physical_name from sys.database_files where name ='C:\t1dat2.ndf'
F.使文件组成为默认文件组
下面的示例使Test1FG1成为默认文件组。 然后,默认文件组被重置为 PRIMARY 文件组。 请注意,必须使用括号或引号分隔 PRIMARY。
USE master;
GO
ALTER DATABASE AdventureWorks2012
MODIFY FILEGROUP Test1FG1 DEFAULT;
GO
ALTER DATABASE AdventureWorks2012
MODIFY FILEGROUP [PRIMARY] DEFAULT;
GO
查询指定表被分配的extent信息
在SQL Server可以使用dbcc extentinfo命令查询表被分配的extent信息。
dbcc extentinfo(数据库名,表名)