2010-01-06 92 views
1

我們的應用程序需要向SQL Server 2005數據庫添加大量文本(單個記錄最多1 GB)。出於性能方面的考慮,這是通過對每個塊進行存儲過程調用(比如usp_AddChunk)來完成的。 usp_AddChunk沒有任何顯式的事務。如何減少批量nvarchar(最大)更新的事務日誌增長

我所看到的是,將塊大小從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倍。

我不會發布的代碼,但這裏的一些細節:

  1. 我打電話SqlConnection.BeginTransaction()
  2. 我使用不同的SqlCommand對於每個大塊
  3. 我從分配的SqlTransaction (1)到每個SqlCommand
  4. 我通常關閉每個SqlCommand執行後的連接,但我也試過不關閉連接,結果相同

這個方案有什麼缺陷?讓我知道你是否需要更多信息。謝謝!

注:使用簡單或大容量日誌恢復模式是不是一種選擇

回答

3

如果「塊」你的意思是這樣的:

UPDATE table 
SET blob = blob + @chunk 
WHERE key = @key; 

那麼你是正確的操作完全記錄。您應該遵循BLOB usage guidelines和使用.WRITE方法chuncked更新:

UPDATE table 
SET blob.Write(@chunk, NULL, NULL) 
WHERE key = @key; 

這將微創日誌更新(如果可能的話,請參閱Operations That Can Be Minimally Logged):

UPDATE語句完全記錄;然而,使用.WRITE 子句的大數據數據類型的部分更新被最小化記錄。

不僅如此,這是最低限度記錄,但由於更新是在BLOB的結束的明確寫入時,引擎會知道,你只更新BLOB的一部分,並只記錄。當您使用SET [email protected]進行更新時,te引擎會看到整個BLOB已經收到一個新值,並且不會檢測到您確實只通過追加新數據來更改BLOB的事實,因此它將記錄整個BLOB(多次你已經找到了)。

BTW,你應該使用的8040多種尺寸的大塊:

爲了獲得最佳性能,我們建議 數據被插入或 塊大小是8040個 字節的倍數更新。

+0

順便說一句,在全記錄模型中,使用.WRITE時只會看到日誌大小的減少,因爲引擎知道您正在進行部分更新而不是整個BLOB列更新。 – 2010-01-06 19:55:22

+0

感謝您的詳盡解答。不幸的是 - 我忽略了這一點 - 該列實際上是XML(用XML標籤包裝的大量文本),而.WRITE不適用於XML列。 – Chris 2010-01-06 22:38:40

+0

每個單獨的塊是有效的XML呢?你可以嘗試column.modify,使用XML X-Query插入來追加塊,但我不確定這是如何工作的日誌空間。見http://msdn.microsoft.com/en-us/library/ms175466.aspx – 2010-01-06 22:49:02

0

你可能做的是圍繞在每個組塊的「塊」或一組與它自己的事務,每組後提交。用你自己的ADO事務圍繞整個事物本質上與隱式事務做同樣的事情,所以這將無濟於事。你必須承諾以更小的塊來保持日誌更小。