为什么不重建页数 <1000 的索引?

use*_*104 19 index sql-server maintenance

我使用 Ola Hallengrens 脚本进行索引维护。在我这样做之前,我使用以下查询来查看哪些索引碎片化最多:

SELECT dbschemas.[name] as 'Schema',
dbtables.[name] as 'Table',
dbindexes.[name] as 'Index',
indexstats.avg_fragmentation_in_percent,
indexstats.page_count
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id]
INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id]
AND indexstats.index_id = dbindexes.index_id
ORDER BY indexstats.avg_fragmentation_in_percent desc
Run Code Online (Sandbox Code Playgroud)

在我的情况下,avg_fragmentation超过70%15个指数和超过30%28个指数。

因此,我使用 Ola Hallengren 的解决方案重建每个索引。当我再次运行查询时,结果如下:

碎片超过70%12个索引,超过30%15个索引。

我想,原因是page_count,对于每个仍然非常碎片化的索引,它都低于 1000。例如,apage_count 为 967的索引之一的 碎片百分比为98,98%!对我来说,重建该索引似乎值得!我做了,然后,碎片是0%。此外,apage_count为 132的指数从95%变为0%

所以,我的问题是,不重建这些索引的原因是什么?一个原因可能是重建需要时间和资源,但由于索引很小,这是否意味着它需要的资源相对较少,无论如何重建仍然是有益的?

该站点上有多个相关问题,但所有这些问题都回答了为什么索引不会碎片整理的问题,或者如果索引很小并且您不对其进行碎片整理是否仍然有用,而这里的语句确实减少了碎片,问题是,为什么不这样做呢?

Pau*_*ite 21

关于最少页数的指导有些武断。减少碎片化的最大好处是:

  1. 它可以提高范围扫描的预读性能;和
  2. 它可以提高页面密度(每页的行数)

根据定义,这两个因素对于小索引都不那么重要。

重建小索引的反驳论点本质上是:

“何必呢?你就没有更重要的事情要操心吗?”

也就是说,重建/重组不是免费的。在某些情况下,避免额外的工作和日志生成可能是值得的(例如,如果日志由于多种可能的原因在 WAN 上传送/复制 - 镜像、可用性组、复制......)。此外,除非(或者即使在某些情况下)您在线重建,重建可能会通过锁定影响其他并发进程。最后,对于小索引,由于来自混合区的分配,重建甚至可能不会减少碎片(除非您在启用跟踪标志 1118 的情况下运行)。

如果你仍然觉得重建这些小索引更快乐,而且不介意后果,那么一定要改变@PageCountLevel传递给 Ola 过程的参数的值。

有关所有详细信息,请参阅Paul Randal 关于索引碎片的演示PASS 电视录音

您可能还想观看 Brent Ozar 谈论为什么索引碎片在 SQL Server 中无关紧要。