我有一个表,它在两列上有一个聚簇索引 - 表的主键。 它的定义如下:
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,遗憾的是我没有空间来创建临时表。如果有办法在没有创建临时表的情况下进行,请告诉我。答案 0 :(得分:11)
这不是对您的问题的完整答案,但请确保如果您在表格上有任何其他索引,那么首先删除它们。否则,当您删除聚簇索引时,SQL Server将不得不重新构建它们,然后在添加新的聚簇索引时再次重建它们。通常的步骤是:
答案 1 :(得分:8)
如果你的表的大小达到1 TB并且可能有很多行,我强烈建议不要使聚簇索引更胖!
首先,删除并重新创建聚簇索引会至少一次将所有数据混乱 - 仅此一段时间就会花费很长时间。
其次,您尝试创建的大型复合聚簇索引将显着增加所有非聚集索引的大小(因为它们包含每个叶节点上的整个聚簇索引值,用于书签查找)。
问题更多:你为什么要这样做?难道你不能只用这些列添加另一个非聚集索引来覆盖你的查询吗?为什么这必须是聚集索引?我认为没有任何优势......
有关索引,尤其是聚簇索引争论的更多信息,请参阅有关SQL Server索引的Kimberly Tripp's blog - 非常有用!
马克
答案 2 :(得分:4)
创建一个新表:
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以来就没有这种方式。
页面上的数据以正确的顺序存储。页面可以按任何物理顺序存储在磁盘上。