因为包含了最左侧和最右侧的边界情况,所以此分区函数将创建 25 个分区。该表将保留第 25 个分区为空白。不需要为这个空分区指定特殊的文件组(因为其中永远不会包含数据)作为限制表数据的约束。要将数据定向至相应的磁盘,可以使用分区架构将分区映射到文件组。分区架构将为 24 个将要包含数据的文件组使用明确的文件组名,而为第 25 个空分区使用 PRIMARY 文件组。
CREATE PARTITION SCHEME [TwoYearDateRangePScheme] AS PARTITION TwoYearDateRangePFN TO ( [FG1], [FG2], [FG3], [FG4], [FG5], [FG6], [FG7], [FG8], [FG9], [FG10],[FG11],[FG12], [FG13],[FG14],[FG15],[FG16],[FG17],[FG18], [FG19],[FG20],[FG21],[FG22],[FG23],[FG24], [PRIMARY] ) GO
通过使用默认的文件组或用户定义的文件组作为未分区的表,或者使用架构创建分区表,可以使用与以前的版本支持的相同语法创建表。哪种方法更好取决于表的填充方式和创建的分区数。从性能角度看,先填充堆再建立群集索引可能要胜过在已经建立索引的表中加载数据。另外,如果有多个 CPU,您可以通过并行 BULK INSERT 语句将数据加载到表中,然后也以并行方式建立索引。对于 Orders 表,按照正常的方式创建表,然后通过 INSERT SELECT 语句(从 AdventureWorks 示例数据库中提取数据)加载现有的数据。要将 Orders 表建为分区表,请在该表的 ON 子句中指定分区架构。Orders 表是使用以下语法创建的:
CREATE TABLE SalesDB.[dbo].[Orders] ( [PurchaseOrderID] [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] NULL CONSTRAINT OrdersRangeYear CHECK ([OrderDate] >= '20021001' AND [OrderDate] < '20041001'), [TotalDue] [money] NULL ) ON TwoYearDateRangePScheme(OrderDate) GO
因为 OrderDetails 表也将使用此架构,而且必须包含 OrderDate ,所以使用以下语法创建 OrderDetails 表:
CREATE TABLE [dbo].[OrderDetails]( [OrderID] [int] NOT NULL, [LineNumber] [smallint] NOT NULL, [ProductID] [int] NULL, [UnitPrice] [money] NULL, [OrderQty] [smallint] NULL, [ReceivedQty] [float] NULL, [RejectedQty] [float] NULL, [OrderDate] [datetime] NOT NULL CONSTRAINT OrderDetailsRangeYearCK CHECK ([OrderDate] >= '20021001' AND [OrderDate] < '20041001'), [DueDate] [datetime] NULL, [ModifiedDate] [datetime] NOT NULL CONSTRAINT [OrderDetailsModifiedDateDFLT] DEFAULT (getdate()), [LineTotal] AS (([UnitPrice]*[OrderQty])), [StockedQty] AS (([ReceivedQty]-[RejectedQty])) ) ON TwoYearDateRangePScheme(OrderDate) GO
加载数据的下一步是通过两个 INSERT 语句处理的。这两个语句使用新的 AdventureWorks 数据库(从中复制数据)。请安装 AdventureWorks 示例数据库以复制此数据:
INSERT dbo.[Orders] SELECT o.[PurchaseOrderID] , o.[EmployeeID] , o.[VendorID] , o.[TaxAmt] , o.[Freight] , o.[SubTotal] , o.[Status] , o.[RevisionNumber] , o.[ModifiedDate] , o.[ShipMethodID] , o.[ShipDate] , o.[OrderDate] , o.[TotalDue] FROM AdventureWorks.Purchasing.PurchaseOrderHeader AS o WHERE ([OrderDate] >= '20021001' AND [OrderDate] < '20041001') GO INSERT dbo.[OrderDetails] SELECT od.PurchaseOrderID , od.LineNumber , od.ProductID , od.UnitPrice , od.OrderQty , od.ReceivedQty , od.RejectedQty , o.OrderDate , od.DueDate , od.ModifiedDate FROM AdventureWorks.Purchasing.PurchaseOrderDetail AS od JOIN AdventureWorks.Purchasing.PurchaseOrderHeader AS o ON o.PurchaseOrderID = od.PurchaseOrderID WHERE (o.[OrderDate] >= '20021001' AND o.[OrderDate] < '20041001') GO
现在,数据已加载到分区表中,您可以使用新的内置系统函数来确定数据所在的分区。下面的查询很有用,因为它将返回包含数据的每个分区的以下信息:每个分区内存在的行数以及最小和最大 OrderDate 。此查询不会返回不包含行的分区。
SELECT $partition.TwoYearDateRangePFN(o.OrderDate) AS [Partition Number] , min(o.OrderDate) AS [Min Order Date] , max(o.OrderDate) AS [Max Order Date] , count(*) AS [Rows In Partition] FROM dbo.Orders AS o GROUP BY $partition.TwoYearDateRangePFN(o.OrderDate) ORDER BY [Partition Number] GO SELECT $partition.TwoYearDateRangePFN(od.OrderDate) AS [Partition Number] , min(od.OrderDate) AS [Min Order Date] , max(od.OrderDate) AS [Max Order Date] , count(*) AS [Rows In Partition] FROM dbo.OrderDetails AS od GROUP BY $partition.TwoYearDateRangePFN(od.OrderDate) ORDER BY [Partition Number] GO
最后,在填充表后,可以建立群集索引。在本例中,群集索引将根据主键进行定义,因为分区键标识两个表(对于 OrderDetails ,在索引中添加 LineNumber 以确保唯一性)。为分区表建立索引的默认行为是将索引与同一架构中的分区表对齐,而该架构是不需要指定的。
ALTER TABLE Orders ADD CONSTRAINT OrdersPK PRIMARY KEY CLUSTERED (OrderDa






