如何根据日期创建分区表?

jra*_*ara 7 sql-server-2008 sql-server partitioning ddl

我正在尝试创建一个分区表,其中分区由OrderDate. 我正在尝试创建一个clustered indexonOrderDate和一个nonclustered primary keyon OrderID。但我收到一条错误消息:

消息 1908,级别 16,状态 1,第 1 行 列“OrderDate”是索引“PK_OrderID”的分区列。唯一索引的分区列必须是索引键的子集。消息 1750,级别 16,状态 0,行 1 无法创建约束。请参阅以前的错误。

如何修改它以使其工作:

CREATE TABLE dbo.Orders
    (
      OrderID INT NOT NULL ,
      Name NVARCHAR(20) NULL ,
      OrderDate DATE NOT NULL ,
    )
ON  PartSchemeOrders(OrderDate)

CREATE CLUSTERED INDEX IX_OrderDate
 on dbo.Orders (OrderDate)
 on PartSchemeOrders(OrderDate)

ALTER TABLE dbo.Orders
    ADD CONSTRAINT PK_OrderID PRIMARY KEY NONCLUSTERED  (OrderID)
Run Code Online (Sandbox Code Playgroud)

Pau*_*ite 11

正如错误消息所说,任何分区对齐的唯一索引都必须在索引键中包含分区键。存在此要求,因此引擎可以在更新时强制执行唯一性,而无需检查每个分区。

在您的情况下,这意味着包含OrderDate在非聚集索引键中,或具有非对齐索引。两者都是可能有效的选择,具体取决于您的情况。为了保持对齐,您的表和索引定义将是:

CREATE TABLE dbo.Orders
(
    OrderID     integer NOT NULL,
    Name        nvarchar(20) NULL,
    OrderDate   date NOT NULL,

    CONSTRAINT PK__Orders_OrderID_OrderDate
        PRIMARY KEY NONCLUSTERED 
            (OrderID, OrderDate)
        ON PS (OrderDate)
)
ON PS (OrderDate);
GO
CREATE CLUSTERED INDEX CX__Orders_OrderDate
ON dbo.Orders (OrderDate)
ON PS (OrderDate);
Run Code Online (Sandbox Code Playgroud)

当然,这会改变非聚集索引强制执行的唯一性。现在,只有组合OrderID,并OrderDate保证是唯一的。理论上可以添加重复的OrderIDs,只要 sOrderDate不同。您是否可以接受这种语义变化取决于您的情况,但这是需要注意的。

另一种方法是让非聚集主键不对齐:

CREATE TABLE dbo.Orders
(
    OrderID     integer NOT NULL,
    Name        nvarchar(20) NULL,
    OrderDate   date NOT NULL,

    CONSTRAINT PK__Orders_OrderID
        PRIMARY KEY NONCLUSTERED 
            (OrderID)
        ON [PRIMARY]
)
ON PS (OrderDate);
GO
CREATE CLUSTERED INDEX CX__Orders_OrderDate
ON dbo.Orders (OrderDate)
ON PS (OrderDate);
Run Code Online (Sandbox Code Playgroud)

这保留了OrderID单独的唯一性,并且对使用索引进行计算MINMAX聚合的查询有一些好处,但是您无法SWITCH在不删除主键并在切换操作后重新创建主键的情况下进行分区进出。

您可以在联机丛书中的这一部分阅读更多关于分区的内容,并在Remus Rusanu 的这个优秀回答中阅读更多关于对齐和非对齐索引的问题