Qual é o tamanho de lote recomendado para SqlBulkCopy?


87

Qual é o tamanho de lote recomendado SqlBulkCopy? Estou procurando uma fórmula geral que possa usar como ponto de partida para o ajuste de desempenho.

Respostas:


97

Tenho um utilitário de importação localizado no mesmo servidor físico que minha instância do SQL Server. Usando um personalizado IDataReader, ele analisa arquivos simples e os insere em um banco de dados usando SQLBulkCopy. Um arquivo típico tem cerca de 6 milhões de linhas qualificadas, com média de 5 colunas decimais e texto curto, cerca de 30 bytes por linha.

Diante desse cenário, descobri que um tamanho de lote de 5.000 é o melhor compromisso de velocidade e consumo de memória. Comecei com 500 e experimentei com maiores. Descobri que 5000 é 2,5x mais rápido, em média, do que 500. Inserir as 6 milhões de linhas leva cerca de 30 segundos com um tamanho de lote de 5.000 e cerca de 80 segundos com tamanho de lote de 500.

10.000 não era mensuravelmente mais rápido. Subir para 50.000 melhorou a velocidade em alguns pontos percentuais, mas não vale a pena aumentar a carga no servidor. Acima de 50.000 não mostraram melhorias na velocidade.

Esta não é uma fórmula, mas é outro ponto de dados para você usar.


3
Uma coisa a se considerar é se a tabela está vazia e possui índices. Nesses casos, você pode querer fazer upload de tudo em um lote, conforme mencionado aqui: technet.microsoft.com/en-us/library/ms177445(v=sql.105).aspx "Se você importar dados em massa para uma tabela vazia com índices e você especificar o tamanho do lote, a tabela se torna vazia após o primeiro lote. Começando com o segundo lote, os dados são totalmente registrados. Para tabelas indexadas vazias, considere realizar a importação em massa em um único lote. "
Sal de

SqlBulkCopy transmite os dados da fonte (por exemplo, DataTable) para Sql, então o que "aumento de carga no servidor" ele tem em um tamanho de lote grande? (por exemplo, 50.000)
BornToCode

29

Este é um problema que também passei algum tempo examinando. Estou procurando otimizar a importação de grandes arquivos CSV (16+ GB, mais de 65 milhões de registros e crescendo) em um banco de dados SQL Server 2005 usando um aplicativo de console C # (.Net 2.0). Como Jeremy foi já apontado , você vai precisar fazer algum ajuste fino para as suas circunstâncias particulares, mas eu recomendo que você tem um tamanho de lote inicial de 500, e teste de valores acima e abaixo desta.

Recebi a recomendação de testar valores entre 100 e 1000 para o tamanho do lote nesta postagem do fórum do MSDN , e estava cético. Mas quando testei tamanhos de lote entre 100 e 10.000, descobri que 500 era o valor ideal para meu aplicativo. O valor de 500 para SqlBulkCopy.BatchSizetambém é recomendado aqui .

Para otimizar ainda mais sua operação SqlBulkCopy, verifique este conselho do MSDN ; Acho que usar SqlBulkCopyOptions.TableLock ajuda a reduzir o tempo de carregamento.


Eu diria que executar o comando de cópia em massa no próprio servidor provavelmente seria mais rápido.
Capitão Kenpachi de

16

Como outros afirmaram, isso depende do seu ambiente, especificamente do volume da linha e da latência da rede.

Pessoalmente, eu começaria definindo a BatchSizepropriedade para 1000 linhas e veria como isso funciona. Se funcionar, continuo dobrando o número de linhas (por exemplo, para 2.000, 4.000 etc.) até atingir o tempo limite.

Caso contrário, se um tempo limite ocorrer em 1000, eu diminuo o número de linhas pela metade (por exemplo, 500) até que funcione.

Em cada caso, continuo dobrando (se tiver êxito) ou reduzindo pela metade (se falhar) a diferença entre cada um dos dois últimos tamanhos de lote tentados até encontrar um ponto ideal.

O outro fator a considerar é quanto tempo leva para copiar um único lote de linhas. Os tempos limite ocorrerão se o lote de linhas sendo copiadas exceder a BulkCopyTimeoutpropriedade que por padrão é 30 segundos. Você pode tentar dobrar a BulkCopyTimeoutpropriedade para 60 segundos. Isso permite um período de tempo mais longo para que um conjunto maior de linhas de lote seja copiado. Por exemplo, um lote de 50.000 linhas pode levar cerca de 40 segundos, apenas excedendo o limite de tempo de 30 segundos, portanto, aumentá-lo para 60 segundos pode ajudar no desempenho.


4

Tudo isso depende da sua implementação.

Que tipo de velocidade você pode esperar em sua rede? Você está usando no Forms ou ASP.Net? Você precisa alertar o usuário sobre o progresso? Qual é o tamanho do trabalho total?

Na minha experiência, executar uma cópia em massa sem um tamanho de lote especificado causará problemas de tempo limite. Eu gosto de começar com algo como 1000 registros e fazer alguns ajustes a partir daí.


Velocidade: Varia, WebForms: Sim, ASP.NET: Sim, Tabelas largas: Sim, Tabelas estreitas, Sim. Milhares de linhas: sim. Milhões de linhas: sim. Se você consegue pensar em um cenário, provavelmente estou fazendo isso.
Jonathan Allen

1
Eu tenho que ficar com minha resposta anterior então. Eu não acho que haja uma bala de prata.
Jeremy

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.