在SQL 2005中更改聚簇索引(PK)的最佳方法

时间:2009-04-01 14:30:10

标签: sql sql-server-2005 indexing primary-key clustered-index

我有一个表,它在两列上有一个聚簇索引 - 表的主键。 它的定义如下:

ALTER TABLE Table ADD  CONSTRAINT [PK_Table] PRIMARY KEY CLUSTERED 
(
  [ColA] ASC,
  [ColB] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]

我想删除此聚簇索引PK并添加如下所示的聚簇索引,并使用非聚集索引添加主键约束,如下所示。

CREATE CLUSTERED INDEX [IX_Clustered] ON [Table] 
(
  [ColC] ASC,
  [ColA] ASC,
  [ColD] ASC,
  [ColE] ASC,
  [ColF] ASC,
  [ColG] ASC
)WITH (PAD_INDEX  = ON, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF,     DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 90, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = OFF) ON [PRIMARY]

ALTER TABLE Table ADD CONSTRAINT
  PK_Table PRIMARY KEY NONCLUSTERED 
  (
    ColA,
    ColB
  ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

我打算删除PK聚簇索引,然后添加新聚簇索引,然后添加非聚集主键索引,但我了解到删除现有聚簇索引会导致表数据重新排序(请参阅在这里回答What happens when I drop a clustered primary key in SQL 2005),我认为不应该这样做。该表敲了1 TB,所以我真的想避免任何不必要的重新排序。

我的问题是,从现有结构到所需结构的最佳方法是什么?

编辑:只是想澄清一下。该表是1TB,遗憾的是我没有空间来创建临时表。如果有办法在没有创建临时表的情况下进行,请告诉我。

4 个答案:

答案 0 :(得分:11)

这不是对您的问题的完整答案,但请确保如果您在表格上有任何其他索引,那么首先删除它们。否则,当您删除聚簇索引时,SQL Server将不得不重新构建它们,然后在添加新的聚簇索引时再次重建它们。通常的步骤是:

  1. 删除所有非聚集索引
  2. 删除聚集索引
  3. 添加新的聚集索引
  4. 添加所有非聚集索引

答案 1 :(得分:8)

如果你的表的大小达到1 TB并且可能有很多行,我强烈建议不要使聚簇索引更胖!

首先,删除并重新创建聚簇索引会至少一次将所有数据混乱 - 仅此一段时间就会花费很长时间。

其次,您尝试创建的大型复合聚簇索引将显着增加所有非聚集索引的大小(因为它们包含每个叶节点上的整个聚簇索引值,用于书签查找)。

问题更多:你为什么要这样做?难道你不能只用这些列添加另一个非聚集索引来覆盖你的查询吗?为什么这必须是聚集索引?我认为没有任何优势......

有关索引,尤其是聚簇索引争论的更多信息,请参阅有关SQL Server索引的Kimberly Tripp's blog - 非常有用!

马克

答案 2 :(得分:4)

  1. 创建一个新表:

    CREATE TABLE newtable (colA INT, colB INT)
    
    • 将旧表中的所有值插入新表:

      INSERT INTO新表格 选择 * 从表

    • 放下旧桌子:

      DROP TABLE表

    • 将新表重命名为旧表

      EXEC sp_rename'newtable','table'

    • 构建索引:

      ALTER TABLE表 添加约束 PK_Table PRIMARY KEY NONCLUSTERED ( 可乐, COLB )WITH(STATISTICS_NORECOMPUTE = OFF,IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)ON [PRIMARY]

答案 3 :(得分:-1)

群集索引实际上并不会更改自己存储在表中的数据的物理顺序。自SQL 6.5以来就没有这种方式。

页面上的数据以正确的顺序存储。页面可以按任何物理顺序存储在磁盘上。