【问题标题】:Having to rebuild indexes twice on a table必须在表上重建索引两次
【发布时间】:2009-08-11 17:25:36
【问题描述】:

我在一个全新的 SQL 2005 数据库中有一个表。作为我们应用程序部署的一部分,我们加载了大约 260 万行的表。一旦完成,表上的索引都将被重建。然后用户被允许进入系统并且对该表的查询超时。然后我可以重建索引(使用导入后使用的完全相同的脚本)并且查询速度非常快。

我已检查索引重建后表没有其他主要数据更改。关于其他可能导致此行为的任何想法?

以下是索引重建脚本的示例:

DROP INDEX dbo.My_Table.Index1
DROP INDEX dbo.My_Table.Index2

ALTER INDEX PK_My_Table ON dbo.My_Table REBUILD

CREATE NONCLUSTERED INDEX Index1 ON dbo.My_Table (column_1 ASC)
CREATE NONCLUSTERED INDEX Index2 ON dbo.My_Table (column_2 ASC)

【问题讨论】:

    标签: sql-server-2005 indexing


    【解决方案1】:

    统计数据,可能,但不在索引上

    优化器将获取第一个查询的更改行数/无统计信息。它决定重建/创建统计数据。

    但是:可能存在与索引无关的列级统计信息。

    第二次重建与统计目的无关,因为列统计信息已经存在,但它强制执行计划被丢弃并重新评估

    编辑:

    SQLServerPedia:

    ...列统计信息未触及 索引重建过程...

    【讨论】:

      【解决方案2】:

      我怀疑第一次简单地添加索引并没有重建统计信息。加载后尝试在表上执行 DBCC DBREINDEX。您可能还想确保您有一个聚集索引。

      【讨论】:

      • PK上有聚集索引。不过感谢您的想法。
      【解决方案3】:

      也许完成索引需要很长时间。第一次重建索引后等了多久?

      更新:我发现这确实是周末的事情,这意味着索引在第一次时就无法正常工作。在那种情况下,除了到目前为止所说的之外,我没有任何建议。

      【讨论】:

      • 我们通常在周末测试导入,在周日和周一早上完成,但仍然存在问题。当我运行脚本时,只需 2 到 5 分钟即可完成。不过感谢您的建议。
      【解决方案4】:

      删除索引之前你做你的数据的大容量插入。这将允许更快地插入数据。在加载数据之前,还要禁用相关表上的任何触发器。

      然后,添加您的索引。这样可以避免您当前正在进行的不必要的冗余索引重建。

      另外,正如一位用户已经指出的那样,使用 DBCC DBREINDEX 比删除和重新添加索引更有意义。当然你也可以update statistics

      更新:由于不推荐使用 DBCC DBREINDEX(命令,而不是概念),请使用带有 REBUILD 选项的 ALTER INDEX。

      【讨论】:

      • 感谢您的建议。导入不是直接的批量插入。更新统计信息并不能解决大数据变化引起的问题,例如碎片等。我相信 DBCC DBREINDEX 正在为 SQL Server 做准备。
      【解决方案5】:

      我会假设您的导入过程中的某些内容会导致索引数据分布在许多数据页中。重建它们可以解决这个问题。

      【讨论】:

      • 感谢您的建议。问题的症结在于,第一次重建并没有解决它。在用户报告问题后,我总是必须第二次这样做。
      【解决方案6】:

      我记得在某处读到 SQL Server 在创建索引时使用当前统计信息。如果统计信息已过时,正在创建的索引可能会针对错误的情况进行优化,并给出表现不佳的结果。

      尝试在创建索引之前更新表上的统计信息。

      BOL 中的UPDATE STATISTICS 条目表明这可能发生:

      数据库引擎保留有关每个索引中键值分布的统计信息,并使用这些统计信息来确定要在查询处理中使用哪些索引。用户可以使用 CREATE STATISTICS 语句创建非索引列的统计信息。查询优化取决于分布步骤的准确性:

      • 如果索引中的键值发生重大变化,请对该索引重新运行 UPDATE STATISTICS。
      • 如果索引列中的大量数据已添加、更改或删除(即,如果键值的分布已更改),或者已使用 TRUNCATE TABLE 语句截断表然后重新填充,请使用更新统计数据。

      由于您已将数百万行导入到一个空表中,我会说您遇到了上述情况之一。

      【讨论】:

      • 感谢您的帖子。我会尝试更新统计信息,但我认为您对该过程的理解有点偏离。统计信息不用于创建索引 - 它们用于确定查询计划以及应该使用哪些索引。索引创建仅依赖于它所索引的数据。
      • 是的,你是对的。我将创建与重新索引混为一谈。我认为我最初阅读的内容是指某些重新索引命令(也不会更新统计信息)在重新索引时实际上使用当前统计信息。不过我现在找不到对此的引用,所以它也可能是错误的。
      猜你喜欢
      • 1970-01-01
      • 2020-09-06
      • 1970-01-01
      • 2022-11-17
      • 2022-01-19
      • 1970-01-01
      • 2012-11-17
      • 1970-01-01
      • 2020-01-01
      相关资源
      最近更新 更多