我们的应用需要向SQL Server 2005数据库添加大量文本(单条记录最多1 GB)。出于性能原因,这是通过对每个块(例如,usp_AddChunk)进行存储过程调用来以块的形式完成的。 usp_AddChunk没有任何明确的交易。
我所看到的是,将块大小从100MB减少到10MB会导致大量的事务日志。我被告知这是因为每次调用usp_AddChunk时,“隐式”(我的术语)事务将记录所有现有文本。因此,对于150MB的记录:
100MB块大小:100(记录0字节)+ 50(记录100 MB)= 100 MB记录
将小于
10 MB块大小:10(记录0字节)+ 10(记录10 MB)+ 10(记录20 MB)... + 10(记录140 MB)=记录1050 MB
我认为通过在我的C#代码中打开一个事务(在我添加第一个块之前,并在最后一个块之后提交),这个“隐式”事务不会发生,我可以避免巨大的日志文件。但我的测试表明,使用ADO.NET事务,事务日志的增长速度提高了5倍。
我不会发布代码,但这里有一些细节:
这个方案的缺陷是什么?如果您需要更多信息,请告诉我。谢谢!
注意:使用简单或批量记录的恢复模型不是一个选项
答案 0 :(得分:3)
如果用'chunks'表示类似的话:
UPDATE table
SET blob = blob + @chunk
WHERE key = @key;
然后你是对的,操作已完全记录。您应该遵循BLOB usage guidelines并使用.write方法进行分组更新:
UPDATE table
SET blob.Write(@chunk, NULL, NULL)
WHERE key = @key;
这将最低限度地记录更新(如果可能,请参阅Operations That Can Be Minimally Logged):
UPDATE语句已完全记录; 但是,部分更新到大 使用.WRITE来估计数据类型 条款记录最少。
不仅记录最少,而且因为更新是BLOB末尾的显式写入,引擎会知道您只更新了BLOB的一部分并且只记录那个。当您使用SET blob=blob+@chunk
te引擎更新时,将看到整个BLOB已收到新值,并且不会检测到您实际上只是通过附加新数据来更改BLOB这一事实,因此它将记录整个BLOB(好几次,正如你已经发现的那样。)
顺便说一句,你应该使用大小为8040的块:
为获得最佳性能,我们建议您这样做 插入或更新数据 块大小是8040的倍数 字节。
答案 1 :(得分:0)
您可能需要做的是围绕每个“块”或一组块使用它自己的事务并在每个组之后提交。使用您自己的ADO事务围绕整个事务基本上与隐式事务执行相同的操作,因此这将无济于事。您必须提交较小的块以保持日志更小。