包含TEXT列的表不断增长

DBD*_*ave 5 sql-server sql-server-2005

我们在生产系统中有一个表(由于遗留原因)运行SQL 2005(9.0.5266)并包含一个TEXT列(以及其他一些不同数据类型的列).

突然之间(从一周前开始)我们注意到这一个表的大小每天线性增加10-15GB(而之前它一直保持恒定大小).该表是消息传递系统的队列,因此其中的数据每隔几秒就会完全刷新一次.在任何时候,可能存在从0行到大约1000行的任何地方,但是当插入消息并且发送消息时它会快速波动(此时它们被删除).

我们在增长开始的那天找不到任何改变的东西 - 所以在这个阶段没有明显的潜在原因.

一个"明显的"罪魁祸首是TEXT列,因此我们检查现在是否存储了任何大量值,但是(使用DATALENGTH)我们发现大约32k左右没有单行.我们运行CHECKDB,更新空间使用,重建所有索引等 - 没有减小大小(并且CHECKDB没有显示错误).

我们查询了sys.allocation_units,大小增加肯定是LOB_DATA(显示total_pages和used_pa​​ges以恒定速率一起增加).

为了减少昨晚的数据库大小,我们简单地创建了一个新表与所讨论的一个表(幸运的是通过应用程序的视图引用),删除旧表,并重命名新表.我们昨晚离开了,因为我们已经缓解了太空问题而感到安慰,而且我们对这个狡猾的桌子进行了备份,以便今天进一步调查.但是,今天早上表的大小已经达到14GB(并且还在增长),而表中通常只有~500行,而MAX(DATALENGTH(text_column))只显示大约35k.

关于什么可能导致这种"失控"增长的任何想法,或者我们可以尝试或查询以获得有关使用该空间究竟是什么的更多信息的任何其他内容?

干杯,戴夫

Rem*_*anu 1

这是处理队列时的一个普遍问题。链接的文章讨论了 Service Broker 队列,但对于用作队列的普通表来说,问题是相同的。如果您有一个拥有大量资源(CPU、内存、磁盘 IO)的繁忙系统,并且您将该系统上的队列推至高吞吐量,那么这些资源的很大一部分将用于处理两个操作:入队(即 INSERT )和出列(即删除)。然而,记录的完整生命周期需要三个操作:INSERT、DELETE 和 Ghost purge。它们在 CPU/内存/磁盘 IO 需求方面的成本大致相同,因此,如果您将该队列用于 90% 的系统资源,那么您应该为每个队列分配 30% 的资源。但只有前两个是在您的控制之下(即在用户会话中运行的显式语句)。第三个是ghost purge,是一个由SQL Server控制的后台进程,不可能允许ghost清理进程消耗30%的资源。这是一个根本问题,如果您将踏板踩到金属上足够长的时间,您的*就会踩到它。一旦幽灵记录累积并超过系统/工作负载特定阈值,性能将迅速下降,症状将急剧恶化,导致性能恶化(形成负反馈循环)。

幸运的是,由于您不使用 Service Broker 队列,而是使用实际表作为队列,因此您可以使用一些更好的工具,例如ALTER TABLE REORGANIZEALTER TABLE REBUILD。到目前为止,最好的解决方案是在线索引/表重建。SQL Server 2012 支持对包含 BLOB 的表进行在线操作,您可以利用它。当然,您必须摆脱已弃用的过时TEXT类型并使用VARCHAR(MAX),但这不言而喻。

作为旁注:

如果您的页面上只有幽灵记录,那么您将不会再次阅读这些页面,并且它们不会被标记为清理

这是不正确的。只有重影的页面将被扫描检测到并清除。正如我所说,问题不在于检测,而在于资源。如果你足够推动你的系统,你就会跑在幽灵清理之前,而他永远不会追上。