重新索引大表 - 我怎么搞砸了?

时间:2009-03-27 16:27:54

标签: sql sql-server sql-server-2005 database-design indexed

我有一个1 TB,600米的行表,它有一个误导的索引列选择,特别是主键列上的聚簇索引,它从不在select查询中使用。

我想从此行中删除聚集索引,并在许多其他行上创建它。

表格目前是这样的:

  • colA(PK,nvarchar(3))[聚集指数pt b]

  • colB(PK,bigint)[聚集索引pt a]

  • colC(日期时间)[非聚集索引]

  • colD(Money)[非聚集索引]

  • colE(位)[无索引]

  • colF(位)[无索引]

  • colG(int)[no index]

  • 更多非索引列

我想将其更改为:

  • colA(PK,nvarchar(3))[聚集索引pt a]

  • colB(PK,bigint)[非聚集索引]

  • colC(日期时间)[非聚集索引]

  • colD(Money)[聚集索引pt d]

  • colE(位)[聚集索引pt b]

  • colF(位)[聚集索引pt c]

  • colG(int)[聚集索引pt e]

  • 更多非索引列

两个问题: 1)您认为此更改需要多长时间(消息结束时的服务器规范)。不幸的是,它是一个实时数据库,我不能在不知道它将要用多长时间的情况下停机。

2)在聚集索引中添加这么多列是不是很糟糕?更新几乎从未执行过。有许多插入和许多选择总是使用所有建议的索引行作为选择参数。

服务器规范:RAID 5,MS-SQL Sever 2005中的5 x 15kRPM驱动器以及一些使它们保持运行的位。

8 个答案:

答案 0 :(得分:9)

首先,我会避免使聚集索引比它绝对要宽。将它分为五个部分似乎是反作用的。此化合物中的所有列聚集索引是否稳定,例如从不改变??

如果没有,我会不惜一切代价避免它们。聚集索引应为:

  • 独特
  • 稳定
  • 尽可能地缩小

您可以更改非聚集索引 - 没问题。但是要避免使聚集索引变得混乱!这肯定会降低你的表现!

查看Kimberly Tripp关于索引的优秀博客文章:

马克

答案 1 :(得分:6)

我做了改动,但没花太长时间。 以下是每个操作的时间,第一次是在具有单个7200RPM驱动器的备份服务器上运行,第二次是在主服务器上,在RAID中具有15k驱动器。

ALTER TABLE Table DROP CONSTRAINT [PK_Table]

2:39小时/ 19分钟

CREATE CLUSTERED INDEX [IX_Clustered] ON [Table] 
(
 [a] ASC,
 [b] ASC,
 [c] ASC,
 [d] ASC,
 [e] ASC,
 [f] 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]

15:30 / 2小时

ALTER TABLE Table ADD CONSTRAINT
PK_hands PRIMARY KEY NONCLUSTERED 
(
 e,
 h
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

4小时/ 1小时

现在最常用的选择查询需要< 10秒钟,通常需要10到15分钟。好的改进!插入时间似乎也快一些。

答案 2 :(得分:3)

您应该拥有一个具有类似规范的开发环境,您可以使用它来获取实时数据库的副本。

答案 3 :(得分:2)

虽然更改聚簇索引听起来像肯定会有帮助,但为什么不先尝试添加(非聚集)覆盖索引?

在构建新索引时不应该删除表,并且应该指示哪些性能改进(如果有)将导致此重组。

答案 4 :(得分:0)

您可能不需要担心停机时间,因为它可能是possible to do the change live(没有任何停机时间)。适用于SQL Server 2005 Enterprise Edition。

答案 5 :(得分:0)

如果有磁盘空间,可以做的一件事就是使用正确的聚簇索引创建第二个表,通过增量过程将这些行复制到新表中几天。一旦所有行都存在,就会在两个表上执行sp_rename(这只需要几分钟的停机时间。如果您的应用程序引用了一个视图而不是物理表,那么您可以完成此操作,并且不会对应用程序造成停机。我希望这有助于

[编辑] 您还必须处理对行的更新,您需要在源表上提供时间戳或上次更新的字段,以便在复制完所有行后同步更新。

答案 6 :(得分:0)

1)您认为此更改需要多长时间(消息结束时的服务器规范)。不幸的是,它是一个实时数据库,如果不知道它将持续多长时间,我就无法停机。

确实,真的取决于数据。仅仅表参数不能提供足够的信息。可能是几分钟(不太可能)到几天(不太可能),最有可能的时间介于两者之间。

2)在聚集索引中添加这么多列是一个可怕的想法吗?更新几乎从未执行过。有许多插入和许多选择总是使用所有建议的索引行作为选择参数。

不,这不应该造成任何问题。只有在进行少量更新时才能提高性能。当这些更新发生时,修复索引需要一段时间,并且在此期间性能将受到影响,这将根据数据而变化。

- 亚当

答案 7 :(得分:0)

我同意Brian的意见,你应该有一个具有相同数据量的测试数据库并运行索引更改。但是,我认为您正在进行此更改,因为您认为它会加快查询速度。您应该运行基准测试(在索引更改之前和之后),并确保您的优化不会变成悲观。