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

是否需要定期重建索引?

评论

相关文章-何时更新统计信息?

#1 楼

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

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

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

如果索引的碎片在10%到30%之间,我将对索引进行REORGANIZE,对统计信息进行UPDATE。如果索引的碎片率超过30%,我将对索引进行REBUILD-不包含UPDATE STATISTICS,因为REBUILD会解决这个问题。请记住,尽管重建仅更新直接与索引关联的统计对象。其他列统计信息将需要单独维护。

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

#2 楼


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

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

是否存在定期重建索引的情况?是否由于日常活动而定期变得支离破碎?您应该安排定期重建吗?它们应该多久运行一次?
汤姆·凯特(Tom Kyte)在这个经典的《问汤姆》线程中建议:

两次索引重建之间的时间间隔应该大约永远。
... />不知道怎么说更好-索引要大而胖,并要有额外的空间。它在您更新的列上-将索引条目在索引中的不同位置移动。该行有一天的代码是“ A”,第二天的代码是“ G”,然后是“ Z”,然后是“ H”,依此类推。因此,该行的索引条目在索引中移动。这样,它需要空间-如果空间不存在,我们将把块分成两部分-并腾出空间。现在,该指数正在发胖。随着时间的推移,索引是启动时大小的2-3倍,并且是“一半或更多为空”,但这是可以的,因为您在四处移动行。现在,当我们四处移动行时,我们不再需要拆分块来腾出空间-该空间已经可用。
然后您来重建或删除并重新创建索引(它们具有相同的效果-只是重建是“更安全的”-不会丢失索引,而且可以更快,因为可以通过扫描现有索引而不是扫描表并进行排序和构建新索引来重建索引。现在,所有的美好空间都消失了。我们重新开始重新分割块的过程-让我们回到开始的地方。
您没有节省任何空间。
索引恰好回到了原来的状态。
您只是在浪费时间来重新构建它,从而导致这种恶性循环重复发生。

这里的逻辑是合理的,但它偏向于读取大量的负载配置文件。
A实际上,“胖”索引(即有很多空隙的索引)确实为新行和移动行保留了足够的空间,从而减少了页面拆分并保持了写入速度。但是,当您从该胖索引中读取数据时,您将必须阅读更多页面才能获得相同的数据,因为您现在正在筛选更多的空白空间。这样会减慢读取速度。
因此,在需要读取大量数据的数据库中,您需要定期重建或重新组织索引。 (多长时间一次以及在什么条件下?Matt M已经对这个问题有一个具体的答案。)在经历大致相等的读写活动的数据库中,或者在大量写入的数据库中,您可能会通过重建索引来损害数据库的性能。定期。

#3 楼

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

评论


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

– LowDBA-约翰·麦考尔(John McCall)
17/12/14在21:22



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

–RDFozz
17年12月14日在22:21

#4 楼

正如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


评论


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

– Max Vernon♦
17年12月14日在21:34

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

– LowDBA-约翰·麦考尔(John McCall)
17年12月14日在21:54

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

–RDFozz
17年12月14日在22:37

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

–amandamaddox3
17年12月16日在2:50

#5 楼


什么时候应该重建索引?


当索引碎片百分比超过30%时。


是否有理由定期重建索引吗?


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

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

https:/ /ola.hallengren.com/

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

评论


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

– bmg002
16-10-17在17:22



#6 楼

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

如果不能解决问题,或者执行此操作的原因仅是要安抚您监视的某个指标,因为它可能会使情况变得更好,那么您所要做的就是消耗CPU和IO,并可能使您的问题变得更糟。

有一个论点是,解决碎片化问题不会使区别于您的服务器,因此值得定期进行吗?

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

http://brentozar.com/go/defrag