什么时候应该重建索引?


Answers:


41

冒我的回答过于笼统的风险,我会说您应该定期运行索引维护过程。但是,您的索引维护过程应仅重建/重新组织特别需要它的索引。

这提出了一个问题:何时需要重建或重组索引?罗兰多很好地谈到了这一点。再次,我冒着极大的风险。当碎片级别对性能造成不利影响时,索引需要维护。碎片级别可能会根据索引的大小和组成而有所不同。

对于SQL Server,我倾向于选择索引大小和索引碎片级别,从这一点开始执行索引维护。如果索引少于100页,我将不进行维护。

如果索引的碎片在10%到30%之间,我将REORGANIZE编制索引和UPDATE统计信息。如果索引的碎片率超过30%,我将REBUILD使用-否UPDATE STATISTICS,因为这会由照顾REBUILD。请记住,尽管重建仅更新直接与索引关联的统计对象。其他列统计信息将需要单独维护。

这个答案实际上只是一个很长的说法:是的,您应该执行例行索引维护,但只能在需要它的索引上进行。


19

什么时候应该在关系数据库(例如SQL Server)中重建索引?

当索引因特殊事件而变得高度分散时,您应该重建索引。例如,您将大量数据加载到索引表中。

是否需要定期重建索引?

那么,如果您的索引由于常规活动而定期变得零散怎么办?您应该安排定期重建吗?他们应该多久运行一次?

汤姆·凯特Tom Kyte)在这个经典的《问汤姆》(Ask Tom)主题中建议:

索引重建之间的时间差应该大约永远。

...

不知道怎么说更好-索引要大而胖,并要有额外的空间。它在您更新的列上-将索引条目在索引中的不同位置移动。该行有一天的代码是“ A”,第二天的代码是“ G”,然后是“ Z”,然后是“ H”,依此类推。因此,该行的索引条目在索引中移动。这样,它需要空间-如果空间不存在,将需要将空间分成两部分-并留出空间。现在,该指数正在发胖。随着时间的推移,索引是启动时大小的2-3倍,并且是“一半或更多的空”,但这是可以的,因为您在四处移动行。现在,当我们四处移动行时,我们不再需要拆分块来腾出空间-该空间已经可用。

然后,您开始重建或删除并重新创建索引(具有相同的效果-只是重建“更安全”-不会失去索引,并且可以更快地重建索引)扫描现有索引,而不是扫描表并进行排序和构建新索引)。现在,所有的美好空间都消失了。我们重新开始重新划分区块的过程-让我们回到开始的地方。

您没有节省空间。

该索引恢复了原来的状态。

您只是在浪费时间来重新构建它,从而导致这种恶性循环不断重复。

这里的逻辑是合理的,但是它偏重于读取大量负载。

“胖”索引(即有很多空白的索引)的确确实为新行和移动行保留了足够的空间,从而减少了页面拆分并保持了写入速度。但是,当您从该胖索引中读取数据时,您将必须阅读更多的页面才能获得相同的数据,因为您现在正在筛选更多的空白空间。这会减慢您的阅读速度。

因此,在需要读取大量数据的数据库中,您希望定期重建或重新组织索引。(多长时间一次以及在什么条件下?Matt M已经对这个问题有一个具体的答案。)在经历大致相等的读写活动的数据库中,或者在大量写入的数据库中,您可能会通过重建索引来损害数据库的性能。经常。


11

大多数人会定期对其进行重建,以使他们永远不会分散。您何时需要重建它们取决于它们破碎的速度。一些索引将需要经常重建,而其他一些索引则基本上不需要重建。查看SQLFool放在一起的脚本,该脚本可以为您解决很多问题。


仅供尊敬的读者参考,SQLFool的脚本在5年内没有得到更新,因此它在执行任务时可能不会包含最新的内容。
LowlyDBA

实际上,我相信上次检查该站点(现在无法访问该站点(可能不是一个好兆头))时,Michelle不再在SQL Server中积极工作,也没有积极地打算进一步处理该脚本。 。如果它对您有用,那就太好了!对于新安装,请考虑Ola Hallengren的脚本:我已经使用了这两个脚本,这并不是一个艰难的过渡。
RDFozz '17

7

正如Matt M接受的答案中指出的那样,一条普遍的经验法则是应重建碎片超过30%的索引。

此查询将帮助您查找有多少索引碎片超过30%(当有一些索引时,应重建它们):

SELECT DB_NAME() AS DBName,
       OBJECT_NAME(ind.object_id) AS TableName,
       ind.name AS IndexName,
       indexstats.index_type_desc AS IndexType,
       indexstats.avg_fragmentation_in_percent,
       indexstats.fragment_count,
       indexstats.avg_fragment_size_in_pages,
       SUM(p.rows) AS Rows 
  FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
         INNER JOIN sys.indexes AS ind ON (    ind.object_id = indexstats.object_id
                                           AND ind.index_id = indexstats.index_id)
         INNER JOIN sys.partitions AS p ON (    ind.object_id = p.object_id
                                            AND ind.index_id = p.index_id)
 WHERE indexstats.avg_fragmentation_in_percent > 30
 GROUP BY
       OBJECT_NAME(ind.object_id),
       ind.name,
       indexstats.index_type_desc,
       indexstats.avg_fragmentation_in_percent,
       indexstats.fragment_count,
       indexstats.avg_fragment_size_in_pages 
 ORDER BY indexstats.avg_fragmentation_in_percent DESC

1
这没有提供答案。问题不是我如何通过“ x”压缩找到索引,而是“何时重建索引”。
Max Vernon

1
这不能为问题提供答案。一旦您拥有足够的声誉,您就可以在任何帖子中发表评论;相反,请提供不需要问询者澄清的答案。- 来自评论
LowlyDBA

2
@LowlyDBA-可能有点简洁,但是我认为它回答了问题,并为讨论提供了有用的信息。我已经对其进行了扩展以解释如何进行。阿曼达(Amanda)-如果我的编辑似乎过多不正确,请随时将其回滚!
RDFozz

谢谢RDFozz。看起来不错。是的,超过30%的碎片需要重建。
amandamaddox3

5

什么时候应该重建索引?

当索引碎片百分比大于30%时。

是否需要定期重建索引?

没有这种情况,但是通常,每周维护一次,在周末进行一次索引维护是保持环境稳定的最佳做法。

我建议使用Ola Hallengren的维护脚本(最佳维护脚本),根据您的环境自定义脚本,并安排它们在周末运行。

https://ola.hallengren.com/

注意:重建索引后,请不要忘记更新统计信息,因为重建索引不会更新所有统计信息。


我很确定你的笔记不正确。索引重建不会更新统计信息。索引没有重组。尽管它仅更新与索引相关的对象的统计信息,但不是所有统计信息。话虽这么说,我建议也经常更新统计信息,以减少由于参数嗅探和过时的统计信息导致查询计划不佳而导致速度降低的可能性。
bmg002

1

与IT中的大多数事情一样,这取决于。您正在尝试通过重建索引来解决什么问题?您能证明它确实可以解决问题吗?如果是这样,请调整数字,直到找到解决问题所需的最少维护。

如果它不能解决问题,或者您执行此操作的原因只是为了使监视的指标令人满意,因为它可能会使情况变得更好,那么您正在做的就是消耗CPU和IO,并可能使问题变得更糟。

有一个论点是,修复碎片不会对您的服务器造成任何影响,所以值得定期进行吗?

https://www.brentozar.com/archive/2017/12/index-maintenance-madness/

http://brentozar.com/go/defrag

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.