您的位置:首页 > 数据库

SQL Server 2005 中的分区表和索引 [6]

2008-12-30 11:18 549 查看
管理将要移入的分区的分段表

1.
创建分段表(将来的伪造分区)。这个分段表必须有一个约束,将其数据限制为只对要创建的分区有效的数据。为了获取更好的性能,将数据加载到未建立索引且未应用约束的堆中,然后在将表移入分区表之前添加约束(参见步骤 3)WITH CHECK。
CREATE TABLE SalesDB.[dbo].[OrdersOctober2004]
(
[OrderID] [int] NOT NULL,
[EmployeeID] [int] NULL,
[VendorID] [int] NULL,
[TaxAmt] [money] NULL,
[Freight] [money] NULL,
[SubTotal] [money] NULL,
[Status] [tinyint] NOT NULL,
[RevisionNumber] [tinyint] NULL,
[ModifiedDate] [datetime] NULL,
[ShipMethodID] [tinyint] NULL,
[ShipDate] [datetime] NOT NULL,
[OrderDate] [datetime] NOT NULL,
[TotalDue] [money] NULL
) ON [FG1]
GO

在自动化过程中:此表很容易创建,因为它总是代表当前月份。根据进程运行的时间,使用 DATENAME(m, getdate()) 等内置函数检测月份是很容易的。因为表的结构必须与现有表相匹配,所以每个月的主要变动是表名称。但是,您可以为每个月使用相同的名称,因为将表添加到分区中之后,表即不需要再存在。虽然将数据移入分区表后该表仍然存在,但您可以在移动操作完成后删除分段表。另外,必须更改日期范围。因为您要处理的是 datetime 数据,而在时间的存储方式方面又存在舍入问题,所以必须能够通过编程方式确定正确的毫秒值。要确定月末最后的 datetime 值,最容易的方法是将正在处理的月份加上 1 个月,然后再减去 2 或 3 毫秒。不能只减去 1 毫秒,因为 59.999 会上舍入为 .000,即下个月的第一天。可以减去 2 或 3 毫秒,因为 2 毫秒将向下舍入为 .997,而 3 毫秒等于 .997;.997 是可以存储的有效值。这样即可确定 datetime 范围的正确结束值:
DECLARE @Month             nchar(2),
@Year             nchar(4),
@StagingDateRange       nchar(10)
SELECT @Month = N'11', @Year = N'2004'
SELECT @StagingDateRange = @Year + @Month + N'01'
SELECT dateadd(ms, -2, @StagingDateRange)

每个月会重新创建表,因为它需要保留在要移入和移出数据的文件组中。要确定要处理的相应文件组,请将以下系统表查询与前面介绍的 $partition 函数结合使用。指定要移出的范围内的任何日期。这是要在其中执行所有操作的分区和文件组。带有下划线的部分需要针对特定的表、分区函数和特定的日期进行更改。
SELECT ps.name AS PSName,
dds.destination_id AS PartitionNumber,
fg.name AS FileGroupName
FROM (((sys.tables AS t
INNER JOIN sys.indexes AS i
ON (t.object_id = i.object_id))
INNER JOIN sys.partition_schemes AS ps
ON (i.data_space_id = ps.data_space_id))
INNER JOIN sys.destination_data_spaces AS dds
ON (ps.data_space_id = dds.partition_scheme_id))
INNER JOIN sys.filegroups AS fg
ON dds.data_space_id = fg.data_space_id
WHERE (t.name = 'Orders') AND (i.index_id IN (0,1)) AND
dds.destination_id = $partition.TwoYearDateRangePFN('20021001')
2.
加载包含数据的分段表。如果文件是一致的,此过程应该通过 BULK INSERT 语句执行。

在自动化过程中:这是自动化过程最复杂的部分。您需要确保所有文件都已经加载,还应考虑并行加载这些文件。跟踪加载了哪些文件以及文件位置的表可以帮助您控制此过程。您可以创建一个 SQL Agent 作业,每隔几分钟检查一次文件,拾取新文件并执行多个 BULK INSERT 语句。
3.
加载数据后,即可添加约束。为了使数据可信,必须添加约束 WITH CHECK。WITH CHECK 设置是默认的,因此不需要指定,但一定不能设置为 WITH NOCHECK。
4.
为分段表建立索引。分段表必须与其要移入的表(成为该表的一个分区)具有相同的群集索引。
ALTER TABLE [OrdersOctober2004]
ADD CONSTRAINT OrdersOctober2004PK
PRIMARY KEY CLUSTERED (OrderDate, OrderID)
ON [FG1]
GO

在自动化过程中:这是一个非常容易的步骤。使用步骤 1 中的月份和文件组信息,可以创建此群集索引。
ALTER TABLE SalesDB.[dbo].[OrdersOctober2004]
WITH CHECK
ADD CONSTRAINT OrdersRangeYearCK
CHECK ([OrderDate] >= '20041001'
AND [OrderDate] <= '20041031 23:59:59.997')
GO
管理将要移出的分区的第二个分段表。

1.
创建第二个分段表。这是一个空表,用于存储移出的分区中的数据。
CREATE TABLE SalesDB.[dbo].[OrdersOctober2002]
(
[OrderID] [int] NOT NULL,
[EmployeeID] [int] NULL,
[VendorID] [int] NULL,
[TaxAmt] [money] NULL,
[Freight] [money] NULL,
[SubTotal] [money] NULL,
[Status] [tinyint] NOT NULL,
[RevisionNumber] [tinyint] NULL,
[ModifiedDate] [datetime] NULL,
[ShipMethodID] [tinyint] NULL,
[ShipDate] [datetime] NOT NULL,
[OrderDate] [datetime] NOT NULL,
[TotalDue] [money] NULL
) ON [FG1]
GO
2.
为分段表建立索引。分段表必须与其要移入的表(成为该表的一个分区,而该分区将成为此表)具有相同的群集索引。
ALTER TABLE [OrdersOctober2002]
ADD CONSTRAINT OrdersOctober2002PK
PRIMARY KEY CLUSTERED (OrderDate, OrderID)
ON [FG1]
GO
将旧数据移出分区表,并将新数据移入分区表

1.
移出旧数据,放入第二个分段表中。
ALTER TABLE Orders
SWITCH PARTITION 1
TO OrdersOctober2002
GO
2.
更改分区函数以删除 2002 年 10 月的边界点。
ALTER PARTITION FUNCTION TwoYearDateRangePFN()
MERGE RANGE ('20021031 23:59:59.997')
GO
3.
此操作还会删除文件组与分区架构之间的关联。具体来说,FG1 将不再是分区架构的一部分。因为您将滚动相同的现有 24 个分区的新数据,所以需要使 FG1 成为“下一个使用的”分区,此分区将是下一个用于拆分的分区。
ALTER PARTITION SCHEME TwoYearDateRangePScheme
NEXT USED [FG1]
GO
4.
更改分区函数,为 2004 年 10 月添加新的边界点。
ALTER PARTITION FUNCTION TwoYearDateRangePFN()
SPLIT RANGE ('20041031 23:59:59.997')
GO
5.
更改基础表的约束定义(如果存在),以允许新范围的数据。因为添加约束的代价可能很昂贵(需要验证数据),所以最好的做法是继续扩大日期范围,而不是删除并重新创建约束。现在,只存在一个约束 (OrdersRangeYearCK),但以后将存在两个约束。
ALTER TABLE Orders
ADD CONSTRAINT OrdersRangeMaxOctober2004
CHECK ([OrderDate] < '20041101')
GO
ALTER TABLE Orders
ADD CONSTRAINT OrdersRangeMinNovember2002
CHECK ([OrderDate] >= '20021101')
GO
ALTER TABLE Orders
DROP CONSTRAINT OrdersRangeYearCK
GO
6.
从第一个分段表中移入新数据。
ALTER TABLE OrdersOctober2004
SWITCH TO Orders PARTITION 24
GO
删除分段表

因为下一个步骤(也是最后一个步骤)将存档所有数据,所以不再需要分段数据。删除表是最快的方式。
DROP TABLE dbo.OrdersOctober2002
GO
DROP TABLE dbo.OrdersOctober2004
GO

备份文件组

最后一步备份的对象是根据您的备份策略选择的。如果选择了基于文件或文件组的备份策略,则应执行文件或文件组备份。如果选择了基于整个数据库的备份策略,则可以执行完整数据库备份或差异备份。
BACKUP DATABASE SalesDB
FILEGROUP = 'FG1'
TO DISK = 'C:/SalesDB/SalesDB.bak'
GO

列表分区:地区数据

如果您的表包含的数据来自多个地区,而通常只对一个地区的数据进行分析,或者定期从每个地区接收数据,请考虑以列表的形式使用已定义的范围分区。换句话说,就是使用函数将每个分区定义为一个地区值。例如,有一家西班牙的公司,它的客户分布在西班牙、法国、德国、意大利和英国。该公司的销售数据总是按国家进行分析。该公司的表可以拥有 5 个分区,每个国家一个分区。

这样一个列表分区的创建过程与日期的范围分区几乎完全相同,不同之处在于,除了实际的分区键外,该范围的边界没有任何其他值。实际上,它是一个列表,而不是范围。尽管它是一个列表,但边界条件必须包含最左侧和最右侧。要创建 5 个分区,只需在分区函数中指定 4 个值。不需要为这些值排序(SQL Server 将在内部为它们排序),但是为了获得正确的分区数,最符合逻辑的方法是对分区值进行排序,将最大值指定给最后一个分区(定义为 LEFT 分区函数时),或者对分区值进行排序,并从倒数第二个值开始(对于 RIGHT)。

因为有 5 个分区,所以必须有 5 个文件组。在本例中,这些文件组根据存储的数据命名。脚本文件 RegionalRangeCaseStudyFilegroups.sql 充分显示了此语法。每个文件组都可以使用相同的设置进行创建,但如果数据不平衡,则不必这么做。只显示了西班牙的文件组和文件;其他四个文件组和文件中都具有相同的参数,但位于不同的驱动器上,而且具有特定于国家分区的名称。
ALTER DATABASE SalesDB
ADD FILEGROUP [Spain]
GO
ALTER DATABASE SalesDB
ADD FILE
(NAME = N'SalesDBSpain',
FILENAME = N'C:/SalesDB/SalesDBSpain.ndf',
SIZE = 1MB,
MAXSIZE = 100MB,
FILEGROWTH = 5MB)
TO FILEGROUP [Spain]
GO

下一步是创建函数,该函数将指定只有四个分区使用 LEFT 作为边界条件。在本例中,列表将包括除英国以外的所有国家,因为英国在按字母顺序排列的列表中位于最后。
CREATE PARTITION FUNCTION CustomersCountryPFN(char(7))
AS
RANGE LEFT FOR VALUES ('France', 'Germany', 'Italy', 'Spain')
GO

要将数据放入根据数据命名的文件组中,分区架构将按字母顺序列出。所有五个文件组都必须在分区架构的语法中指定。
CREATE PARTITION SCHEME [CustomersCountryPScheme]
AS
PARTITION CustomersCountryPFN
TO ([France], [Germany], [Italy], [Spain], [UK])
GO

最后,可以在新的 CustomersCountryPScheme 中创建 Customers 表。
CREATE TABLE [dbo].[Customers](
[CustomerID] [nchar](5) NOT NULL,
[CompanyName] [nvarchar](40) NOT NULL,
[ContactName] [nvarchar](30) NULL,
[ContactTitle] [nvarchar](30) NULL,
[Address] [nvarchar](60) NULL,
[City] [nvarchar](15) NULL,
[Region] [nvarchar](15) NULL,
[PostalCode] [nvarchar](10) NULL,
[Country] [char](7) NOT NULL,
[Phone] [nvarchar](24) NULL,
[Fax] [nvarchar](24) NULL
) ON CustomersCountryPScheme (Country)
GO

尽管范围分区被定义为只支持范围,但它们还为执行其他类型的分区(例如列表分区)提供了一种方法。



返回页首

总结

使用 SQL Server 2005,您可以通过分区轻松一致地管理大量表和索引,从而使您可以在活动表之外管理数据子集。这提供了简化的管理、改善的性能以及抽象的应用程序逻辑,因为分区架构对于应用程序是完全透明的。如果您的数据具有逻辑分组(范围或列表),而大量查询必须分析这些预定义的、一致的范围内的数据,还需要管理这些预定义范围内的传入数据和传出数据,则范围分区是简单的选择。如果您查看对大量数据进行的分析(没有使用特定范围),或者所有查询都访问大多数数据(如果不是所有数据),那么使用多个没有任何特定放置方法的文件组是一种更容易的解决方案,此解决方案还可以改善性能。

本文的脚本

本白皮书代码示例中使用的脚本可以从 SQLServer2005PartitionedTables.zip 文件中找到。下面介绍了该压缩文件中的每个文件。

RangeCaseStudyScript1-Filegroups.sql - 包括用于创建范围分区表案例研究所需的文件组和文件的语法。此脚本是可以修改的,是您可以在更小的磁盘集上使用更小的文件(以 MB 而不是 GB 为单位)创建此示例。此外,它还包含通过 INSERT...SELECT 语句导入数据的代码,使您可以通过相应的分区函数推测数据的位置。

RangeCaseStudyScript2-PartitionedTable.sql - 包括用于创建与范围分区表案例研究相关的分区函数、分区架构和范围分区表的语法。此脚本还包含相应的约束和索引。

RangeCaseStudyScript3-JoiningAlignedTables.sql - 包括说明 SQL Server 为分区表提供的各种连接策略的查询。

RangeCaseStudyScript4-SlidingWindow.sql - 包括与范围分区表案例研究中按月进行管理有关的语法和过程。在此脚本中,您将在 Orders 表中移入和移出数据。您还可以自行决定是否创建相同的过程,以便在 OrderDetails 表中移入和移出数据。提示:请参见 RangeCaseStudyScript2 中为 OrderDetails 插入表和正确数据列而使用的 Insert 语句。

RegionalRangeCaseStudyFilegroups.sql - 包括用于创建地区性分区表案例研究所需的文件组和文件的语法。实际上,这是一个模拟列表分区架构的范围分区。

RegionalRangeCaseStudyPartitionedTable.sql - 包括用于创建与范围分区表案例研究相关的分区函数、分区架构和地区性分区表的语法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: