1

このアプリでは、大量のテキストを SQL Server 2005 データベースに追加する必要があります (1 つのレコードで最大 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 倍大きくなることがわかりました。

コードは掲載しませんが、詳細は次のとおりです。

  1. SqlConnection.BeginTransaction() を呼び出します
  2. チャンクごとに異なる SqlCommand を使用します
  3. (1) の SqlTransaction を各 SqlCommand に割り当てます
  4. 通常、SqlCommand を実行するたびに接続を閉じますが、同じ結果で接続を閉じないようにしました

このスキームの欠陥は何ですか?さらに情報が必要な場合はお知らせください。ありがとう!

注: シンプルまたは一括ログ復旧モデルの使用はオプションではありません

4

2 に答える 2

3

「チャンク」とは、次のような意味です。

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

次に、操作が完全にログに記録されていることは正しいです。BLOB の使用ガイドラインに従い、チャンク更新には .Write メソッドを使用する必要があります。

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

これにより、最小限の更新がログに記録されます (可能な場合は、最低限ログに記録できる操作を参照してください)。

UPDATE ステートメントは完全にログに記録されます。ただし、.WRITE 句を使用した大きな値のデータ型への部分的な更新は、最小限しかログに記録されません。

これが最小限に記録されるだけでなく、更新は BLOB の最後に明示的に書き込まれるため、エンジンは BLOB の一部のみを更新したことを認識し、それのみをログに記録します。teエンジンで更新するとSET blob=blob+@chunk、BLOB全体が新しい値を受け取ったことがわかりますが、実際には新しいデータを追加してBLOBを変更しただけであるという事実を検出しないため、BLOB全体がログに記録されます(数回、すでに判明しています)。

ところで、8040 の倍数のサイズのチャンクを使用する必要があります。

最高のパフォーマンスを得るには、データを 8040 バイトの倍数のチャンク サイズで挿入または更新することをお勧めします。

于 2010-01-06T18:31:23.247 に答える
0

あなたがしなければならないことは、各「チャンク」またはチャンクのグループを独自のトランザクションで囲み、各グループの後にコミットすることです。全体を独自の ADO トランザクションで囲むことは、基本的に暗黙のトランザクションと同じことを行うため、役に立ちません。ログを小さく保つには、小さなチャンクでコミットする必要があります。

于 2010-01-06T17:05:39.963 に答える