索引在系统正常使用期间变得高度碎片化

Mic*_*hal 4 sql-server fragmentation sql-server-2014 index-maintenance

我在我的项目中使用 MS SQL Server 2014 标准版,最近我遇到了在用户正常使用系统期间索引碎片变高的问题。

目前索引在维护窗口期间每天重建一次,但在某些操作之后,一些索引会变得相当高(超过 30%)。另一个问题是,如果有大量数据要处理,碎片会发生在单个进程中,因此我们最终会发现进程启动得相当快,但一旦出现碎片,其性能就会急剧下降。

在这种情况下我能做什么?我不太可能获得额外的维护窗口。我正在考虑定期只重建一些索引,但我担心它最终会导致数据库锁定甚至死锁。

Pau*_*ite 6

如果您可以正确确认碎片确实是一个问题,例如因为当预读变得不那么有效时读取性能显着下降,或者因为系统正在努力跟上页面拆分的数量,您可能会考虑轻轻调整最关键索引的填充因子。这将提高写入性能,但代价是读取和可以缓存的页面数量(在标准版可用的有限缓冲池中)。

不要一开始就对低填充因子发疯。选择一个可管理数量的最有问题的索引,估计在维护窗口之间的正常工作负载期间避免过多拆分所需的可用空间量,并测试设置较低填充因子的效果(通常不低于约 90 % 用于第一次测试)。千万不能只是一味地设置较低的填充因子所有索引。

请记住,十有八九,系统有其他更大的问题,而不是直接归因于次优设置填充因子的问题。您应该监控系统的重要性能方面,并能够根据对真实历史数据的合理技术分析来为任何更改提供理由。

阅读材料:


Jos*_*ell 5

一些选项:

只更新统计

您提到碎片会导致性能问题。很多时候似乎碎片是问题所在,而实际上问题是糟糕的统计数据(由于表中更改了多少数据)。

您最好只更新有关表的统计信息:

  • 在这些大型操作之后,或
  • 按计划(每周,每天,甚至一天几次 - 取决于问题出现的频率)

重建索引会导致更新统计信息,这会强化碎片是问题所在的看法。这些操作的破坏性和资源密集度通常远低于索引重建。

UPDATE STATISTICS dbo.YourTableName WITH FULLSCAN;
Run Code Online (Sandbox Code Playgroud)

您还可以使用“样本百分比”来避免扫描整个表格:

UPDATE STATISTICS dbo.YourTableName WITH SAMPLE 50 PERCENT;
Run Code Online (Sandbox Code Playgroud)

测试不同的采样率时要小心,因为有一个临界点,采样统计数据可能需要比FULLSCAN. 这取决于多种因素(例如您的数据和可用资源)。Erin Stellato 在这里发表了一篇关于该主题的精彩帖子:样本大小和更新统计数据的持续时间:是否重要?

避免造成碎片的常见原因

您可以更改您的架构/工作负载以避免造成碎片的常见原因,从而在问题开始之前减缓或停止问题。uniqueidentifier首选示例是避免通过NEWID().

更一般地说,一个好的聚集索引应该是狭窄的、唯一的、静态的和不断增加的。

在线重建索引

如果在正常用户活动期间重建索引极其重要,您可能必须尝试证明升级到 SQL Server 企业版的合理性。然后你可以指定索引重建发生“ONLINE”

ALTER INDEX [IX_YourIndex] REBUILD WITH (ONLINE = ON);
Run Code Online (Sandbox Code Playgroud)

这可以允许用户活动在索引操作期间继续,而不是在最后(应该是简短的)。当然,重建仍会使用服务器资源,因此可能会影响整体性能。

我把它放在最后,因为它有一个很大的价格标签。在朝着这个方向前进之前,您绝对应该探索其他选项,并进行测试以确保REBUILDs 能够真正解决问题。