幽灵行清理是一个后台进程,用于物理删除被 DML 语句标记为待删除的行。 以下文章概述了此过程。
幽灵行
从索引的叶级页中删除的行不会从该页中被物理移除。 相反,该行会被标记为将来删除,即幽灵行。 这意味着该行仍保留在页面上,但行头中的一个位被更改,以指示该行为“幽灵行”。 这是为了在删除操作期间优化性能。 幽灵行对于行级锁定以及快照隔离事务是必要的,在这些情况下,数据库引擎必须保留较旧的行版本。
虚影清理任务
被标记为待删除(或幽灵化)的行,在不再需要时,将由后台幽灵清理进程进行清理。 幽灵行清理会定期运行,并检查是否有页面包含幽灵行。 如果找到任何行,它会以物理方式删除这些行。 在数据库引擎实例中,所有数据库共用一个幽灵清理线程。
当一行被标记为已删除时,数据库将被标记含有未彻底删除的条目。 幽灵行清理进程仅扫描此类数据库。 虚影清理过程还会将数据库标记为在删除所有虚影行后没有虚影行,并在下次运行时跳过此数据库。 如果无法获取数据库的共享锁,此过程也会跳过任何数据库。 下次运行时,它会对数据库重试锁定获取。
以下查询返回数据库中的大致虚影行数。
SELECT SUM(ghost_record_count) AS total_ghost_records,
DB_NAME(database_id) AS database_name
FROM sys.dm_db_index_physical_stats(NULL, NULL, NULL, NULL, 'SAMPLED')
GROUP BY database_id
ORDER BY total_ghost_records DESC;
禁用幽灵行清理
在删除操作频繁的高负载系统中,如果幽灵行清理进程将缓冲池中许多频繁访问的页面替换为包含幽灵行的其他页面,可能会降低性能。 因此,经常访问的页面必须从磁盘中重新读取,生成额外的磁盘 I/O 并增加查询延迟。 如果发生这种情况,您可以使用跟踪标志 661 禁用幽灵行清理。
如果不进行幽灵行清理,数据库可能会无谓地膨胀,从而因额外的 I/O 和内存消耗而降低性能。 由于虚影清理进程删除标记为虚影的行,因此禁用进程会在页面上保留这些行,从而阻止数据库引擎重用此空间。 这会强制数据库引擎将数据添加到新页面,从而导致数据库文件膨胀,也可能导致 页面拆分。 分页会增加磁盘 I/O,这可以减少查询性能。 如果禁用幽灵清理,数据库可能会耗尽空间。
警告
不建议永久禁用虚影清理过程。
若要在禁用虚影清理时删除虚影行,请在删除行的表上重新生成索引。 重建索引会根据现有数据创建新页,在此过程中会跳过幽灵行。