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

343*_*343 25 sql-server sql-server-2008-r2 partitioning

我有一个包含数据的现有表:

dbo.Test (col1,col2,col3....) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)

我需要将此表更改为这样分区:

dbo.Test(col1,col2,col3....) ON Ps_Date(Col2)
Run Code Online (Sandbox Code Playgroud)

我怎样才能在不删除和重新创建表格的情况下实现这一目标?

Seb*_*ine 56

您没有指定您的表是否有聚集索引,所以让我们来看看所有选项。

我将使用这个示例分区函数、分区方案和表:

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
Run Code Online (Sandbox Code Playgroud)

1. 你的表有一个不是由约束创建的聚集索引。

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

假设已经创建了这个聚集索引的例子:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(Id) ON [PRIMARY];
Run Code Online (Sandbox Code Playgroud)

为了对这个表进行分区,聚集索引将分区列(在我们的例子中是 pt)作为键的一部分。此语句更改聚集索引以包含分区列并同时对其进行分区:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(pc, Id) WITH(DROP_EXISTING = ON)ON ps1(pc) ;
Run Code Online (Sandbox Code Playgroud)

DROP_Existing在创建新索引之前,该子句会自动删除现有索引。这比单独的DROP INDEX更受欢迎,因为它会导致非聚集索引只重建一次。

2. 你的表有一个聚集索引,它是PRIMARY KEYorUNIQUE约束的一部分,它包含分区列作为键的一部分

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

假设PRIMARY KEY已经在表上创建了这个约束:

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

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

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(pc, Id) WITH(DROP_EXISTING = ON)ON ps1(pc) ;
Run Code Online (Sandbox Code Playgroud)

3. 表有一个不包含分区列但作为PRIMARY KEYorUNIQUE约束的一部分创建的聚集索引

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

假设表有一个这样的主键:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY CLUSTERED (Id) ON [PRIMARY];
Run Code Online (Sandbox Code Playgroud)

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

ALTER TABLE dbo.pt DROP CONSTRAINT ptc;
Run Code Online (Sandbox Code Playgroud)

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

CREATE UNIQUE CLUSTERED INDEX ptci ON dbo.pt(pc, Id) ON ps1(pc) ;
Run Code Online (Sandbox Code Playgroud)

如果您选择重新创建PRIMARY KEY非对齐约束,您可以这样做:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY NONCLUSTERED (Id) ON [PRIMARY];
Run Code Online (Sandbox Code Playgroud)

4. 你的表没有聚集索引

在这种情况下,建议在大多数情况下只创建一个聚集索引来建立分区。您可以使用之前看到的 create index 语句:

CREATE UNIQUE CLUSTERED INDEX ptci ON dbo.pt(pc, Id) ON ps1(pc) ;
Run Code Online (Sandbox Code Playgroud)

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

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

ALTER TABLE dbo.pt ADD CONSTRAINT ptc UNIQUE CLUSTERED(pc,id);
Run Code Online (Sandbox Code Playgroud)

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

ALTER TABLE dbo.pt DROP CONSTRAINT ptc WITH(MOVE TO ps1(pc));
Run Code Online (Sandbox Code Playgroud)

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

ALTER TABLE dbo.pt ADD tmp_id INT IDENTITY(1,1);
Run Code Online (Sandbox Code Playgroud)

但是,这将需要排它表锁,直到所有行都被赋值。根据桌子的大小,这可能会持续很长时间。创建该列后,请按照上述两个步骤首先创建UNIQUE约束,然后立即再次删除它。之后,您还可以再次删除该列。所有这些步骤都相当麻烦,因此您最好只在表上创建一个聚集索引。这甚至不必是唯一的。


如果您有企业版,则可以WITH(ONLINE=ON)在上述大多数语句中使用该子句。这将使您的表可用于其他连接。但是,在此期间会对性能产生影响。


Kin*_*hah 25

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

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

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

一些好的资源: