如何对现有的未分区表进行分区


22

我有一个现有的数据表:

dbo.Test (col1,col2,col3....) ON [PRIMARY]

我需要更改此表以进行如下分区:

dbo.Test(col1,col2,col3....) ON Ps_Date(Col2)

我如何在不删除并重新创建表的情况下实现这一目标?

Answers:


23

要对表进行分区,可以按照以下简要步骤操作:

  • 首先创建一个分区函数分区方案
  • 之后,您可以对表进行分区。
  • 如果您的表具有聚簇索引,则需要在正确的分区上删除并重新创建它,或者可以使用DROP_EXISTING子句来重新创建聚簇索引。
  • 如果您的表没有聚集索引,则可以使用分区方案在正确的分区上创建一个索引。
  • 此外,企业版还具有使用ONLINE=ONCREATE INDEX语句选项的灵活性,可以最大程度地减少应用程序的停机时间。请注意,使用ONLINE选项重建索引时会看到性能下降。

若要自动进行分区,您还可以使用Codeplex上的SQL Server分区管理实用程序SQL Server分区表框架

一些好的资源:


53

您没有指定表是否具有聚集索引,因此让我们逐步介绍所有选项。

我将使用此示例分区功能,分区方案和表:

CREATE PARTITION FUNCTION pf1(INT) AS RANGE LEFT FOR VALUES(10,20,30,40);
GO
CREATE PARTITION SCHEME ps1 AS PARTITION pf1 ALL TO ([PRIMARY])
GO
CREATE TABLE dbo.pt(pc INT NOT NULL, id INT NOT NULL) ON [PRIMARY];
GO

1.您的表具有不是由约束创建的聚集索引。

这是最简单的情况。您可以只使用CREATE INDEX带有DROP_EXISTING子句的语句将表移至分区方案。

以该示例为例,该聚簇索引已创建:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(Id) ON [PRIMARY];

为了对该表进行分区,聚簇索引已将分区列(在本例中为pt)作为键的一部分。该语句更改聚集索引以包括分​​区列并同时对其进行分区:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(pc, Id) WITH(DROP_EXISTING = ON)ON ps1(pc) ;

DROP_Existing子句会在创建新索引之前自动删除现有索引。与单独使用相比DROP INDEX,此方法更可取,因为它会使非聚集索引仅重建一次。

2.您的表具有聚集索引,该聚集索引是PRIMARY KEYUNIQUE约束的一部分,并且包含分区列作为键的一部分

这个仍然很简单,并且与前一个非常相似。

假设此PRIMARY KEY约束已在表上创建:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY CLUSTERED (pc, Id) ON [PRIMARY];

现在,您可以运行与在1中使用的相同的重新创建脚本:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(pc, Id) WITH(DROP_EXISTING = ON)ON ps1(pc) ;

3.该表具有聚集索引,该聚集索引不包括分区列,而是作为PRIMARY KEYUNIQUE约束的一部分创建的

倒霉。您不能在事实之后更改a PRIMARY KEYUNIQUE约束的定义。唯一的选择是删除约束,然后重新创建包括分区列的约束,或者创建独立于包含分区列的约束的聚集索引。在第二种情况下,您可以重新创建约束,NONCLUSTERED而无需包括分区列。因为现在此约束未对齐(意味着其支持索引未分区),所以您必须指定将其放置在磁盘上的位置。

假设表具有这样的主键:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY CLUSTERED (Id) ON [PRIMARY];

要对该表进行分区,您必须首先删除约束:

ALTER TABLE dbo.pt DROP CONSTRAINT ptc;

然后,您需要创建分区的聚集索引:

CREATE UNIQUE CLUSTERED INDEX ptci ON dbo.pt(pc, Id) ON ps1(pc) ;

如果选择重新创建PRIMARY KEY不对齐的约束,则可以这样进行:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY NONCLUSTERED (Id) ON [PRIMARY];

4.您的表没有聚集索引

在这种情况下,建议在大多数情况下仅创建聚簇索引来建立分区。您可以为此使用先前看到的create index语句:

CREATE UNIQUE CLUSTERED INDEX ptci ON dbo.pt(pc, Id) ON ps1(pc) ;

但是,如果您有充分的理由不创建聚簇索引,则可以采用以下两步方法。遗憾的是,没有直接的方法可以进行此更改。

假设您的表没有聚集索引。要对表进行分区,您需要首先创建一个CLUSTERED UNIQUE约束。(您也可以使用CLUSTERED PRIMARY KEY约束)。如果您具有唯一的列组合,这是一个简单的步骤:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc UNIQUE CLUSTERED(pc,id);

创建约束后,您可以再次将其删除并同时将表“移动”到新的分区方案:

ALTER TABLE dbo.pt DROP CONSTRAINT ptc WITH(MOVE TO ps1(pc));

如果您没有唯一的列组合,那么您将不走运。在这种情况下,您唯一的选择是添加新列并用唯一值填充它。如果表相当小,则可以执行以下操作:

ALTER TABLE dbo.pt ADD tmp_id INT IDENTITY(1,1);

但是,这将需要排他的表锁定,直到所有行都被赋值为止。根据表的大小,这可能会持续一段时间。创建该列之后,请遵循上述两个步骤来首先创建UNIQUE约束,然后立即将其再次放置。之后,您也可以再次删除该列。所有这些步骤都是相当麻烦的,因此最好在表上创建聚簇索引。那甚至不必是唯一的。


如果您拥有Enterprise Edition,则可以WITH(ONLINE=ON)在上面的大多数语句中使用该子句。这将使您的表可用于其他连接。但是,在这段时间内会对性能产生影响。


1
太好了,萨巴斯蒂安!简直很棒!只是添加到上面的#3 ...如果要使用SWITCH in或out,所有索引必须对齐。进行非聚集,不对齐的PK将不允许您执行SWITCH,除非您先采取以下步骤放下索引,执行SWITCH(无论其方向如何),然后重建索引。这通常仍然比执行删除操作快得多,当然,如果不需要使用SWITCH,就不会有问题。
杰夫·摩登2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.