在今天的文章里,我想谈下SQL Server里非常重要的话题:SQL Server如何处理文件的文件组。当你用CREATE DATABASE命令创建一个简单的数据库时,SQL Server为你创建2个文件:

  • 一个数据文件(.mdf)
  • 一个事务日志文件(.ldf)

数据文件本身在有且只有一个主文件组里创建。默认情况下,在主文件组里,SQL Server存储素有的数据(用户表,系统表等)。那有额外的文件和文件组的目的是什么?我们来看下。

多个文件组

当你为你的数据创建额外的文件组,你可以在它们里面存储你定义的表和索引,这个会在多个方面帮助你

  • 你可以保持你的主文件组很小。
  • 你可以把你的数据分割到多个文件组(例如,你可以在企业版里使用文件分区)。
  • 你可以在文件组级别进行备份和还原操作。这给你在你的备份和还原策略上更多细粒度的控制。
  • 你可以在文件组级别运行DBCC CHECKDB命令,而不是数据库级别。

通常,你应该至少有一个从文件组,这里你可以存储你自己创建的数据库对象。你不应该在主文件组里存储SQL Server为你创建的其他系统对象。

多个文件

当你创建了你自己的文件组,你也要至少放一个文件进去。另外,你可以增加额外的文件到文件组。这也会提高你的负荷性能,因为SQL Server会散步数据在所有的文件间,即所谓的轮询调度分配算法(Round Robin Allocation Algorithm)。第一个64K在第一个文件存储,第二个64k在第二个文件存储,第三个区在第一个文件存储(在你的文件组里,你有2个文件时)。

使用这个方法,SQL Server可以在缓冲池里闩锁分配位图页(PFS,GAM,SGAM)的多个副本,并提高你的负荷性能。你也可以用这个方法解决在TempDb里默认配置的同个问题。另外,SQL Server也会确保文件组的所有文件在同一时间点满——通过所谓的比例填充算法(Proportional Fill Algorithm)。因此,在文件组里你的所有文件有同样的初始大小和自动增长参数非常重要。不然轮询调度分配算法就不能正常工作。

实例演示

现在我们来看下一个实例,如何创建额外文件组里有多个文件在里面的数据库。下列代码展示了你必须用到的CREATE DATABASE命令来完成这个任务。

-- Create a new database
CREATE DATABASE MultipleFileGroups ON PRIMARY
(
-- Primary File Group
NAME = 'MultipleFileGroups',
FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\MultipleFileGroups.mdf',
SIZE = 5MB,
MAXSIZE = UNLIMITED,
FILEGROWTH = 1024KB
),
-- Secondary File Group
FILEGROUP FileGroup1
(
-- 1st file in the first secondary File Group
NAME = 'MultipleFileGroups1',
FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\MultipleFileGroups1.ndf',
SIZE = 1MB,
MAXSIZE = UNLIMITED,
FILEGROWTH = 1024KB
),
(
-- 2nd file in the first secondary File Group
NAME = 'MultipleFileGroups2',
FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\MultipleFileGroups2.ndf',
SIZE = 1MB,
MAXSIZE = UNLIMITED,
FILEGROWTH = 1024KB
)
LOG ON
(
-- Log File
NAME = 'MultipleFileGroups_Log',
FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\MultipleFileGroups.ldf',
SIZE = 5MB,
MAXSIZE = UNLIMITED,
FILEGROWTH = 1024KB
)
GO

创建完数据库后,问题是如何把表或索引放到特定的文件组?你可以用ON关键字人为制定文件组,如下代码所示:

CREATE TABLE Customers
(
FirstName CHAR(50) NOT NULL,
LastName CHAR(50) NOT NULL,
Address CHAR(100) NOT NULL,
ZipCode CHAR(5) NOT NULL,
Rating INT NOT NULL,
ModifiedDate DATETIME NOT NULL,
)
ON [FileGroup1]
GO

另一个选项,你标记特定文件组为默认文件组。然后SQL Server自动创建新的数据库对象在没有指定ON关键字的文件组里。

-- FileGroup1 gets the default filegroup, where new database objects
-- will be created
ALTER DATABASE MultipleFileGroups MODIFY FILEGROUP FileGroup1 DEFAULT
GO

这是我通常推荐的方法,因为你不需要再考虑,在创建完你的数据库对象后。因此现在让我们创建一个新的表,它会自动存储在FileGroup1文件组。

-- The table will be created in the file group "FileGroup1"
CREATE TABLE Test
(
Filler CHAR(8000)
)
GO

现在我们进行简单的测试:我们插入40000条记录到表。每条记录8K大小。因此我们插入了320MB数据到表。这是我刚才提的轮询调度分配算法,会进行操作:SQL Server会在2个文件间发放数据:第一个文件有160M的数据,第二个文件也会有160M的数据。

-- Insert 40.000 records, results in about 312MB data (40.000 x 8KB / 1024 = 312,5MB)
-- They are distributed in a round-robin fashion between the files in the file group "FileGroup1"
-- Each file will get about 160MB
DECLARE @i INT = 1
WHILE (@i <= 40000)
BEGIN
INSERT INTO Test VALUES
(
REPLICATE('x', 8000)
) SET @i += 1
END
GO

接下来你可以在硬盘上看下,你会看到2个文件时同样的大小。

当你把这些文件放在不同的物理硬盘上,你可以同时访问它们。那就是在一个文件组里有多个文件的强大。

你也可以使用下列脚本获取数据库文件的相关信息。

-- Retrieve file statistics information about the created database files
DECLARE @dbId INT
SELECT @dbId = database_id FROM sys.databases WHERE name = 'MultipleFileGroups' SELECT
sys.database_files.type_desc,
sys.database_files.physical_name,
sys.dm_io_virtual_file_stats.* FROM sys.dm_io_virtual_file_stats
(
@dbId,
NULL
)
INNER JOIN sys.database_files ON sys.database_files.file_id = sys.dm_io_virtual_file_stats.file_id
GO

小结

在今天的文章里我向你展示了多个文件组和文件组里多个文件是如何让你的数据库更容易管理,还有文件组里的多个文件是如何使用轮询调度分配算法。

感谢关注!

参考文章

https://www.sqlpassion.at/archive/2016/08/29/files-and-file-groups-in-sql-server/

SQL Server里的文件和文件组的更多相关文章

  1. SQL Server里在文件组间如何移动数据?

    平常我不知道被问了几次这样的问题:“SQL  Server里在文件组间如何移动数据?“你意识到这个问题:你只有一个主文件组的默认配置,后来围观了“SQL Server里的文件和文件组”后,你知道,有多 ...

  2. sql server 里的文件和文件组使用

    转自:https://www.cnblogs.com/woodytu/p/5821827.html 参考:https://www.sqlskills.com/blogs/paul/files-and- ...

  3. SQL Server 2008中删除errorlog文件的方法

    删除error咯个文件[SSQL\MSSQL10.MSSQLSERVER\MSSQL\Log目录下面] 由于默认情况下,SQL Server 保存 7 个 ErrorLog 文件,名为: ErrorL ...

  4. SQL Server里的闩锁介绍

    在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch).闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构.文章的第1部分我会介 ...

  5. SQL Server里一些未公开的扩展存储过程

    SQL Server里一些未公开的扩展存储过程 [转帖] 博客天地 www.inbaidu.com SQL Server里一些未公开的扩展存储过程 扩展存储过程(xp)是直接运行在SQL Server ...

  6. 在SQL Server里我们为什么需要意向锁(Intent Locks)?

    在1年前,我写了篇在SQL Server里为什么我们需要更新锁.今天我想继续这个讨论,谈下SQL Server里的意向锁,还有为什么需要它们. SQL Server里的锁层级 当我讨论SQL Serv ...

  7. 在SQL Server里为什么我们需要更新锁

    今天我想讲解一个特别的问题,在我每次讲解SQL Server里的锁和阻塞(Locking & Blocking)都会碰到的问题:在SQL Server里,为什么我们需要更新锁?在我们讲解具体需 ...

  8. 在SQL Server里如何进行页级别的恢复

    在今天的文章里我想谈下每个DBA应该知道的一个重要话题:在SQL Server里如何进行页级别还原操作.假设在SQL Server里你有一个损坏的页,你要从最近的数据库备份只还原有问题的页,而不是还原 ...

  9. SQL Server里强制参数化的痛苦

    几天前,我写了篇SQL Server里简单参数化的痛苦.今天我想继续这个话题,谈下SQL Server里强制参数化(Forced Parameterization). 强制参数化(Forced Par ...

随机推荐

  1. android——handler机制原理

    在android版本4.0及之后的版本中多线程有明确的分工,子线程可以写所有耗时的代码(数据库.蓝牙.网络服务),但是绝对不能碰UI,想碰UI跟着主线程走,那么我们如何才能让主线程知道我们要对 UI进 ...

  2. SDOI 2016 生成魔咒

    题目大意:一个字符串,刚开始为空,依次在后面添加一个字符,问每次添加完字符后本质不同的字符串有多少种 后缀自动机裸题,添加字符时,更新的结点个数即为新增加的子串 #include<bits/st ...

  3. POOL_TYPE enumeration

    typedef enum _POOL_TYPE { NonPagedPool, NonPagedPoolExecute                   = NonPagedPool, PagedP ...

  4. 再谈SQL Server中日志的的作用

    简介     之前我已经写了一个关于SQL Server日志的简单系列文章.本篇文章会进一步挖掘日志背后的一些概念,原理以及作用.如果您没有看过我之前的文章,请参阅:     浅谈SQL Server ...

  5. 性能计数器与profiler的组合性能诊断

    性能计数器和sql profiler都是常用的性能诊断工具和优化工具,最近和群友聊天发现很多人竟然不知道这两个可以“组合”使用,所以这篇算是一篇扫盲贴吧. 两种工具简述 通过计数器可以收集两部分内容: ...

  6. CoreData教程

    网上关于CoreData的教程能搜到不少,但很多都是点到即止,真正实用的部分都没有讲到,而基本不需要的地方又讲了太多,所以我打算根据我的使用情况写这么一篇实用教程.内容将包括:创建entity.创建r ...

  7. 用FlexGrid做开发,轻松处理百万级表格数据

    表格数据处理是我们项目开发中经常会遇到的设计需求之一,所需处理的数据量也较大,通常是万级.甚至百万级.此时,完全依赖平台自带的表格工具,往往无法加载如此大的数据量,或者加载得很慢影响程序执行. 那么, ...

  8. [备忘]Redis运行出现Client sent AUTH, but no password is set

    原因:程序提供了密码,但是redis.conf中并没有设置密码. 附加问题:如果redis.conf中设置了密码,有可能会导致服务无法启动,报5013错误.可能是访问权限的问题.

  9. C语言 · 寻找数组中的最大值

    问题描述 对于给定整数数组a[],寻找其中最大值,并返回下标. 输入格式 整数数组a[],数组元素个数小于1等于100.输出数据分作两行:第一行只有一个数,表示数组元素个数:第二行为数组的各个元素. ...

  10. [CORS:跨域资源共享] W3C的CORS Specification

    随着Web开放的程度越来越高,通过浏览器跨域获取资源的需求已经变得非常普遍.在我看来,如果Web API不能针对浏览器提供跨域资源共享的能力,它甚至就不应该被称为Web API.从另一方面来看,浏览器 ...