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.
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:
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.
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.BatchSize
també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.
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 BatchSize
propriedade 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 BulkCopyTimeout
propriedade que por padrão é 30 segundos. Você pode tentar dobrar a BulkCopyTimeout
propriedade 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.
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í.
Eu tentei vários tamanhos, no meu caso 5000 era bom