转发记录,修复它们的有效方法

Tho*_*hom 5 performance sql-server maintenance

我正在处理应用程序的 SQL Server 数据库中的问题。此应用程序用于医疗保健,我只维护数据库,我不创建应用程序。

一段时间后,客户面临着他们的表上转发记录的问题。我创建了一个存储过程,通过创建聚集索引并再次删除它来修复这些转发的记录,有效地重新组织表并修复转发的记录。

我当前脚本的工作方式如下:

  1. #Forwarded_Records用来自sys.dm_db_index_physical_statssys.indexes和 的信息填充表 ( ) sys.columns。这将用包含转发记录和有关其索引的信息(包括离线/在线可用性)的表填充该表。

  2. 一旦表被填满,存储过程将检查窗口中是否还有时间做其他工作。如果有,它将从 forwarded_records 表中的第一条记录开始,并开始创建/删除聚集索引。

  3. 一旦修复了所有记录,它将开始重新填充 forwarded_records 表并搜索包含转发记录的新表。这将再次开始循环。

我面临以下问题:

  • 医疗保健每天只提供很小的维护窗口,并且数据库必须运行良好/始终可用 24/7
  • 填充 forwarded_records 表最多可能需要 45 分钟(太长了)。如果找不到转发的记录,情况也是如此。
  • 数据库可以包含 4000 多个表。有些有超过数百万行。我更喜欢首先查找转发记录,而不是将作业应用于所有表(包括不包含任何转发记录的表)

现在我的问题是什么?

我怎样才能改进这个过程,使它更有效。目前它在第一个周期非常有效并且修复了所有转发的记录。但是从第二个周期开始,它只会花更多的时间在“查找”转发记录上而不是修复它们(找到它们需要 45 分钟,而修复它们只需要 2 分钟)。

我的情况有没有更好的方法?我应该每天花 45 分钟来理所当然地找到它们,还是我最好做所有表而不是搜索实际需要修复的表。

感谢您的帮助。

(StackExchange 上的第一篇文章,尽量保持建设性。如果这个问题需要编辑,请帮忙)

Seb*_*ine 3

SQL Server 不会保留转发记录数量的“统计信息”。要返回它必须访问物理表页的数量。如果表很大,则可能需要一段时间。

也就是说,您可以在模式下查询sys.dm_db_index_physical_statsSAMPLED。这将为您提供基于基表 1% 样本的转发记录数的估计值。

或者,您可以将更新数量(请参阅sys.dm_db_index_usage_stats)与每个表上转发的记录数量相关联。假设如果每 10 次更新都会导致转发,那么您可以通过查看执行的更新数量是否比您的阈值高 10 倍来检查表是否超出了您的阈值。查询 sys.dm_db_index_usage_stats 是即时的。但是,每次服务器重新启动时,它都会从新开始累积。

我仍然会定期(可能每月一次)运行 sys.dm_db_index_physical_stats,以确保该比率仍然准确。

要真正删除转发的记录,您可以使用ALTER TABLE dbo.test REBUILD WITH(ONLINE=ON);,但这也会重建堆表上的所有非聚集索引。这应该比创建和删除聚集索引要快得多,聚集索引会重建所有非聚集索引两次。(该WITH(ONLINE=ON)条款需要企业版。)


现在,您必须问自己的更大问题是,数据库中是否真的应该有 4000 个堆。一般来说,精心选择的聚集索引将提高整个系统的性能。存储结构“堆”通常只推荐用于插入次数较多、选择、更新或删除次数很少的表。

在典型的 OLTP 环境中,这只适用于日志表。尝试弄清楚是否可以向表中添加聚集索引,这样您的转发痛苦就会消失。(但是,您需要处理碎片问题,但市场上已经有一些好的(且免费)解决方案;例如Ola Hallengren 的脚本)。