Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在SQL 2005中更改聚集索引(PK)的最佳方法_Sql_Sql Server 2005_Indexing_Primary Key_Clustered Index - Fatal编程技术网

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

在SQL 2005中更改聚集索引(PK)的最佳方法,sql,sql-server-2005,indexing,primary-key,clustered-index,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并添加如下聚集索引,并使用非聚集索引添加主键约束,如下所示

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

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聚集索引,然后添加新的聚集索引,然后添加非聚集主键索引,但我了解到删除现有聚集索引会导致表数据重新排序(请参见此处的答案),我认为这是不必要的。该表的内存不足1 TB,因此我确实希望避免任何不必要的重新排序

我的问题是,从现有结构到理想结构的最佳方式是什么

编辑:我只是想澄清一下。表是1TB,很遗憾,我没有空间创建临时表。如果有一种不创建临时表的方法,请让我知道

  • 创建新表:

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

      CREATE TABLE newtable (colA INT, colB INT)
      
      插入 变成牛顿表 挑选* 从桌子上

    • 删除旧表:

      升降台

    • 将新表重命名为旧表

      EXEC sp_重命名“新表”、“表”

    • 建立索引:

      更改表格 添加约束 PK_表主键非聚集 ( 可乐 马驹 )[主]上的(统计信息\u NORECOMPUTE=OFF,忽略\u DUP\u KEY=OFF,允许\u行\u锁=ON,允许\u页\u锁=ON)


  • 这并不是对您的问题的完整回答,但请确保如果表中有任何其他索引,您首先删除这些索引。否则,SQL Server必须在删除聚集索引时重新生成所有聚集索引,然后在添加回新聚集索引时再次重新生成所有聚集索引。通常的步骤是:

  • 删除所有非聚集索引
  • 删除聚集索引
  • 添加新的聚集索引
  • 添加回所有非聚集索引

  • 如果您的表的大小达到1 TB,并且可能有很多行,我强烈建议不要让聚集索引变得那么胖

    首先,删除和重新创建聚集索引将至少在所有数据周围移动一次,这一过程需要花费很长时间

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

    问题更多:你为什么要这么做??难道你不能用这些列添加另一个非聚集索引,以潜在地覆盖你的查询吗?为什么这必须是聚集索引??我看不出这有什么好处

    有关索引,特别是聚集索引辩论的更多信息,请参阅关于SQL Server索引-非常有用


    Marc

    聚集索引实际上不会改变存储在表中的数据的物理顺序。自SQL6.5以来就没有过这种情况


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

    这不是一个选项。我在一个1.5TB的RAID上有一个1TB的表。SQL Server需要空间进行重新排序和移动。如果空间不足,可以使用DROP INDEX中的“移动到”选项在临时存储上创建表,然后在RAID上重新创建表。您可以将行分块传输,并在传输过程中从源中删除它们。这可能是一个非常缓慢的过程。好吧……为什么创建临时表比删除聚集索引并允许不必要的重新调用要好呢?看起来这将是一样的缓慢和更多的工作。请看这里如何估计新表的大小:嗯,这是我最初的计划,但是删除聚集索引的第二步会导致所有数据移动。我希望以某种方式合并步骤2和步骤3,以避免不必要的数据移动。这是真的吗?我的印象是,数据的物理顺序是由集群键决定的。页面上的数据以正确的顺序存储。页面可以以任何物理顺序存储在磁盘上。您可能希望更新答案以包含此区别。