DEMO
DEMO1 :仅重建某个分区
下面例子是一个简单的分区表,并对索引进行分区后,仅仅重建某个分区,而不是整个索引。比如说表中按照数据冷热进行分区,可以仅仅对热数据进行重建,从而大大减少了重建索引所需的时间,如代码清单1所示。
代码清单1.仅仅重建某个分区,而不是整个索引
--创建分区函数
CREATE PARTITION FUNCTION [t](int) AS RANGE LEFT FOR VALUES (100, 500)
--分区架构
CREATE PARTITION SCHEME [x] AS PARTITION [t] TO ([PRIMARY], [FileGroup1], [FileGroup1])
--创建表
CREATE TABLE [Sales].[SalesOrderDetailPartition](
[SalesOrderID] [int] NOT NULL,
[SalesOrderDetailID] [int] IDENTITY(1,1) NOT NULL,
[CarrierTrackingNumber] [nvarchar](25) NULL,
[OrderQty] [smallint] NOT NULL,
[ProductID] [int] NOT NULL,
[SpecialOfferID] [int] NOT NULL,
[UnitPrice] [money] NOT NULL,
[UnitPriceDiscount] [money] NOT NULL,
[LineTotal] AS (isnull(([UnitPrice]*((1.0)-[UnitPriceDiscount]))*[OrderQty],(0.0))),
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
) ON x(SalesOrderID)
INSERT INTO [Sales].[SalesOrderDetailPartition]([SalesOrderID],
[CarrierTrackingNumber],
[OrderQty] ,
[ProductID] ,
[SpecialOfferID],
[UnitPrice],
[UnitPriceDiscount],ModifiedDate,rowguid)
SELECT [SalesOrderID],
[CarrierTrackingNumber],
[OrderQty] ,
[ProductID] ,
[SpecialOfferID],
[UnitPrice],
[UnitPriceDiscount],ModifiedDate,rowguid FROM [Sales].[SalesOrderDetail]
go
--创建索引分区
CREATE NONCLUSTERED INDEX test_partition_idx ON [Sales].[SalesOrderDetailPartition](ProductID) on x(SalesOrderID)
--仅仅重建某个分区
ALTER INDEX test_partition_idx
ON [Sales].[SalesOrderDetailPartition]
REBUILD Partition = 1
CREATE PARTITION FUNCTION [t](int) AS RANGE LEFT FOR VALUES (100, 500)
--分区架构
CREATE PARTITION SCHEME [x] AS PARTITION [t] TO ([PRIMARY], [FileGroup1], [FileGroup1])
--创建表
CREATE TABLE [Sales].[SalesOrderDetailPartition](
[SalesOrderID] [int] NOT NULL,
[SalesOrderDetailID] [int] IDENTITY(1,1) NOT NULL,
[CarrierTrackingNumber] [nvarchar](25) NULL,
[OrderQty] [smallint] NOT NULL,
[ProductID] [int] NOT NULL,
[SpecialOfferID] [int] NOT NULL,
[UnitPrice] [money] NOT NULL,
[UnitPriceDiscount] [money] NOT NULL,
[LineTotal] AS (isnull(([UnitPrice]*((1.0)-[UnitPriceDiscount]))*[OrderQty],(0.0))),
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
) ON x(SalesOrderID)
INSERT INTO [Sales].[SalesOrderDetailPartition]([SalesOrderID],
[CarrierTrackingNumber],
[OrderQty] ,
[ProductID] ,
[SpecialOfferID],
[UnitPrice],
[UnitPriceDiscount],ModifiedDate,rowguid)
SELECT [SalesOrderID],
[CarrierTrackingNumber],
[OrderQty] ,
[ProductID] ,
[SpecialOfferID],
[UnitPrice],
[UnitPriceDiscount],ModifiedDate,rowguid FROM [Sales].[SalesOrderDetail]
go
--创建索引分区
CREATE NONCLUSTERED INDEX test_partition_idx ON [Sales].[SalesOrderDetailPartition](ProductID) on x(SalesOrderID)
--仅仅重建某个分区
ALTER INDEX test_partition_idx
ON [Sales].[SalesOrderDetailPartition]
REBUILD Partition = 1
关于这里,更深入的文章可以参阅:http://www.mssqltips.com/sqlservertip/1621/sql-server-partitioned-tables-with-multiple-filegroups-for-high-availability/
DEMO2:数据库部分在线和文件还原
代码清单2.备份还原单个文件
--创建测试数据库
CREATE DATABASE test
GO
--改成完整恢复模式
ALTER DATABASE test SET RECOVERY FULL
--添加一个文件组
ALTER DATABASE test
ADD FILEGROUP WW_GROUP
GO
--向文件组中添加文件
ALTER DATABASE test
ADD FILE
( NAME = ww,
FILENAME = 'D:\wwdat1.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB)
TO FILEGROUP ww_Group
--在不同文件组上分别创建两个表
CREATE TABLE test..test ( id INT IDENTITY )
ON [primary]
CREATE TABLE test..test_GR ( id INT IDENTITY )
ON ww_Group
--做完整备份
BACKUP DATABASE test
TO DISK='D:\Test_backup.bak'WITH INIT
--做文件备份
BACKUP DATABASE test
FILE = 'ww',
FILEGROUP = 'ww_Group'
TO DISK='D:\CROUPFILES.bak'WITH INIT
--备份日志
BACKUP LOG test
TO DISK='D:\Test__log.ldf'WITH INIT
--删除文件组中的表内的数据
TRUNCATE TABLE test..test_GR
--还原备份,日志仅仅被应用于那个还原状态的文件
RESTORE DATABASE test
FILE = 'ww',
FILEGROUP = 'ww_Group'
FROM DISK ='D:\CROUPFILES.bak'
WITH FILE = 1,NORECOVERY
RESTORE LOG test
FROM DISK='D:\Test__log.ldf'
WITH FILE = 1, NORECOVERY
--备份尾端日志
BACKUP LOG test
TO DISK='D:\Test__log.ldf' WITH NOINIT,NO_TRUNCATE
--还原尾端日志
RESTORE LOG test
FROM DISK='D:\Test__log.ldf'
WITH FILE = 2, RECOVERY
GO
--查看数据,删除数据的操作被成功恢复
SELECT *
FROM test..test_GR
--清除数据库
DROP DATABASE test
CREATE DATABASE test
GO
--改成完整恢复模式
ALTER DATABASE test SET RECOVERY FULL
--添加一个文件组
ALTER DATABASE test
ADD FILEGROUP WW_GROUP
GO
--向文件组中添加文件
ALTER DATABASE test
ADD FILE
( NAME = ww,
FILENAME = 'D:\wwdat1.ndf',
SIZE = 5MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB)
TO FILEGROUP ww_Group
--在不同文件组上分别创建两个表
CREATE TABLE test..test ( id INT IDENTITY )
ON [primary]
CREATE TABLE test..test_GR ( id INT IDENTITY )
ON ww_Group
--做完整备份
BACKUP DATABASE test
TO DISK='D:\Test_backup.bak'WITH INIT
--做文件备份
BACKUP DATABASE test
FILE = 'ww',
FILEGROUP = 'ww_Group'
TO DISK='D:\CROUPFILES.bak'WITH INIT
--备份日志
BACKUP LOG test
TO DISK='D:\Test__log.ldf'WITH INIT
--删除文件组中的表内的数据
TRUNCATE TABLE test..test_GR
--还原备份,日志仅仅被应用于那个还原状态的文件
RESTORE DATABASE test
FILE = 'ww',
FILEGROUP = 'ww_Group'
FROM DISK ='D:\CROUPFILES.bak'
WITH FILE = 1,NORECOVERY
RESTORE LOG test
FROM DISK='D:\Test__log.ldf'
WITH FILE = 1, NORECOVERY
--备份尾端日志
BACKUP LOG test
TO DISK='D:\Test__log.ldf' WITH NOINIT,NO_TRUNCATE
--还原尾端日志
RESTORE LOG test
FROM DISK='D:\Test__log.ldf'
WITH FILE = 2, RECOVERY
GO
--查看数据,删除数据的操作被成功恢复
SELECT *
FROM test..test_GR
--清除数据库
DROP DATABASE test
代码清单2很好的阐述了整个文件备份还原的过程,其中,在文件还原的过程中我们可以看到数据库本身是在线的,但数据库中有一个文件处于还原状态,如图2所示。
此时对于表test_GR做操作的话,会提示因文件组没有联机而失败,如图3所示。

▲图3.因为文件组没有联机而导致操作失败
再对尾端日志进行备份还原之后,该文件组成功上线。
小结
本篇文章阐述了文件和文件组在高可用性中的作用。了解这些特性对于降低还原时间非常有必要。在数据库开始上线之前,尽量合理的把一个数据库分为多个文件组和文件,不仅仅提升性能和并发性,还可以使得DR更加容易。