Como reduzir o crescimento de log de transações para nvarchar batched atualizações (no máximo)

StackOverflow https://stackoverflow.com/questions/2014670

Pergunta

Nosso aplicativo precisa adicionar grandes quantidades de texto para o SQL Server 2005 banco de dados (até 1 GB para um único registro). Por motivos de desempenho, isso é feito em pedaços, fazendo uma chamada de procedimento armazenado para cada pedaço (digamos, usp_AddChunk). não usp_AddChunk não tem nenhum transações explícitas.

O que eu estou vendo é que a redução do tamanho do bloco de 100MB a resultados 10MB em logs de transação maciçamente maiores. Eu tenho dito isso é porque cada vez usp_AddChunk é chamado, um (meu termo) transação "implícito" registrará todo o texto existente. Assim, para um recorde de 150MB:

100 MB pedaço tamanho: 100 (0 bytes registada) + 50 (100 MB registada) = 100 MB sessão

será menor do que

10 MB do tamanho do fragmento: 10 (0 bytes registada) + 10 (10 MB registada) + 10 (20 MB registada) ... + 10 (140 MB registada) = 1050 MB sessão

Eu pensei que ao abrir uma transação no meu código C # (antes de adicionar o primeiro pedaço, e comprometer-se após o último pedaço), essa transação "implícito" não aconteceria, e eu poderia evitar os enormes arquivos de log. Mas meus testes mostram o log de transações crescendo 5x maior usando a transação ADO.NET.

Eu não vou postar o código, mas aqui está alguns detalhes:

  1. Eu chamo SqlConnection.BeginTransaction ()
  2. Eu uso um SqlCommand diferente para cada pedaço
  3. I atribuir o SqlTransaction a partir de (1) para cada SqlCommand
  4. Eu costumo fechar a conexão depois de cada execução SqlCommand, mas eu também tentei não fechar a conexão com os mesmos resultados

O que é a falha neste esquema? Deixe-me saber se você precisar de mais informações. Obrigado!

Nota: usando um modelo de recuperação de log em massa simples ou não é uma opção

Foi útil?

Solução

Se por 'pedaços' Você quer dizer algo como:

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

Então você está certo de que a operação está totalmente registrado. Você deve seguir o href="http://msdn.microsoft.com/en-us/library/a1904w6t(VS.80).aspx" rel="nofollow noreferrer"> BLOB uso e uso os métodos .Write para atualizações chuncked:

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

Isto irá minimamente registrar a atualização (se possível, consulte operações que podem ser minimamente Conectado ):

A instrução UPDATE está totalmente registrado; no entanto, atualizações parciais para grande tipos de dados de valor usando o .WRITE cláusula são minimamente registradas.

Não só que este é minimamente registrada, mas porque a atualização é um write explícita no final do BLOB, o motor vai saber que você só atualizou uma parte do BLOB e só irá registrar que . Quando você atualizar com SET blob=blob+@chunk te motor vai ver que todo o BLOB recebeu um novo valor e não irá detectar o fato de que você realmente só mudou o BLOB, acrescentando novos dados, de modo a que irá registrar todo o BLOB (várias vezes, como você já descobriu).

BTW você deve usar pedaços de tamanho múltiplo de 8040:

Para um melhor desempenho, recomendamos que ser inseridos ou atualizados nos dados tamanhos do pedaço que são múltiplos de 8040 bytes.

Outras dicas

O que você pode ter que fazer é cercar cada "pedaço" ou grupo de blocos com a sua própria operação e comprometer após cada grupo. Em torno da coisa toda com a sua própria transação ADO é essencialmente fazendo a mesma coisa que a transação implícita faz, de modo que não vai ajudar. Você tem de se comprometer em pedaços menores para manter o log menor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top