我对幽灵清理过程的理解是,它每五秒钟就会寻找删除索引中的幽灵记录。因此它不会使系统过载,它一次只会“清理”大约十页。
那么,这意味着它每五秒只清理大约 8 万条记录吗?似乎我的索引总是充满幻影记录,清理工作永远不会完成。
所以,假设我运行了一个删除操作,可能有一百万行,而这几百万行的索引记录大小大约为 8Gb。所以大约是80k差异的100,000倍。这是否意味着幽灵清理过程将需要 500,000 秒或将近六天才能完成?
很明显,我在这里遗漏了一些东西,因为清除幽灵记录需要那么长时间是没有意义的。那么其他达到相同指数的活动呢?幽灵清理进程会导致等待,还是必须等待其他进程?
[这个问题是由我们在 OpsMgrDW 中看到的性能问题带来的,我们想了解更多关于这个过程的信息]
我写了两篇全面的博客文章来解释幽灵清理(这是唯一在任何地方都深入解释过它的地方,无论是印刷版还是在线版)。
第一个是存储引擎内部:Ghost cleanup 深入,第二个是Ghost cleanup redux。是的,每次 10 页,并且幽灵清理任务可能永远赶不上大量的连续删除。
通过确保存储引擎“看到”幽灵记录,可以积极触发除每 5 秒 10 页之外的幽灵清理。使用类似的东西强制扫描受影响的表或索引
select * from [problem-table] with (index = problem-index)
这将排队请求积极清除幽灵记录。但请注意,它会在执行此操作时生成大量事务日志。作为常规索引维护的一部分,它们还应该通过索引重建或重组来清除。
希望这可以帮助。
我一直认为索引重建会在结构移动时“修复”任何剩余的问题。
几年前,我遇到了这个问题,但无法通过配置、触发幽灵清理或任何类似的方式来解决它。我正在使用一个具有连续插入和删除的数据库,并且由于幽灵清理触发,SQLServer 将有效地定期锁定。
我最终的解决方案是按时间对问题表进行分区,而不是删除旧行,我只能删除旧表。这帮助很大。这对于您的情况可能不可行,但它适用于许多情况,但有一些变化。
我们有类似的情况。我们的一张表有很多幽灵记录,这些记录没有被幽灵清理过程清理。DB Shrinking、DBCC Cleantable、Rebuilding index 和 Reorganizing index 没有用。为了解决这个问题,我们将数据传输到临时表,然后将表截断并将数据传输回截断表。此表包含 LOB 数据(2 个 nvarchar(max) 列)。有没有其他方法可以解决这个问题?