Как уменьшить рост журнала транзакций для пакетных обновлений nvarchar (max) - PullRequest
1 голос
/ 06 января 2010

Наше приложение должно добавлять большие объемы текста в базу данных SQL Server 2005 (до 1 ГБ для одной записи). По соображениям производительности это делается в чанках, путем вызова хранимой процедуры для каждого чанка (скажем, usp_AddChunk). usp_AddChunk не имеет явных транзакций.

Что я вижу, так это уменьшение размера чанка со 100 МБ до 10 МБ, что приводит к значительному увеличению журналов транзакций. Мне сказали, что это потому, что каждый раз, когда вызывается usp_AddChunk, «неявная» (мой термин) транзакция будет регистрировать весь существующий текст. Итак, для записи 150 МБ:

Размер блока 100 МБ: 100 (зарегистрировано 0 байт) + 50 (зарегистрировано 100 МБ) = зарегистрировано 100 МБ

будет меньше

10 МБ Размер блока: 10 (зарегистрировано 0 байт) + 10 (зарегистрировано 10 МБ) + 10 (зарегистрировано 20 МБ) ... + 10 (зарегистрировано 140 МБ) = зарегистрировано 1050 МБ

Я подумал, что, открыв транзакцию в моем коде C # (до того, как я добавлю первый блок и сделаю коммит после последнего блока), эта «неявная» транзакция не произойдет, и я смог бы избежать огромных файлов журнала. Но мои тесты показывают, что журнал транзакций увеличивается в 5 раз при использовании транзакции ADO.NET.

Я не буду публиковать код, но вот несколько деталей:

  1. Я вызываю SqlConnection.BeginTransaction ()
  2. Я использую разные SqlCommand для каждого чанка
  3. Я присваиваю SqlTransaction из (1) каждой SqlCommand
  4. Обычно я закрываю соединение после каждого выполнения SqlCommand, но я также пытался не закрывать соединение с теми же результатами

Какой недостаток в этой схеме? Дайте мне знать, если вам нужно больше информации. Спасибо!

Примечание: использование модели восстановления с простой или массовой регистрацией не вариант

Ответы [ 2 ]

3 голосов
/ 06 января 2010

Если под «кусками» вы подразумеваете что-то вроде:

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, и будет только регистрировать , что, При обновлении с помощью SET blob=blob+@chunk te механизм увидит, что весь большой двоичный объект получил новое значение, и не обнаружит тот факт, что вы действительно изменили большой двоичный объект только путем добавления новых данных, поэтому он будет регистрировать весь большой двоичный объект (несколько раз). , как вы уже узнали).

Кстати, вы должны использовать куски размером, кратным 8040:

Для лучшей производительности мы рекомендуем что данные будут вставлены или обновлены в размеры куска, кратные 8040 байт.

0 голосов
/ 06 января 2010

Что вам, возможно, придется сделать, это окружить каждый «чанк» или группу чанков своей собственной транзакцией и зафиксировать после каждой группы. Все окружение вашей собственной транзакцией ADO по сути делает то же самое, что и неявная транзакция, так что это не поможет. Вы должны сделать коммит меньшими порциями, чтобы журнал был меньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...