Pergunta

Eu estou trabalhando em um aplicativo de desktop que usa o SQLite para inserir a granel de dezenas de milhares de linhas em um banco de dados SQLite. Eu gostaria de ajudar a otimizar o desempenho da inserção em massa. Atualmente, leva 50 segundos para inserir 60 megs no valor de dados no banco de dados.

  • Quais paramentes de string de conexão eu poderia usar para melhorar atuação? Devo alterar o tamanho do buffer? É isso possível através de um Parâmetro de cadeia de conexão? Existem outra cadeia de conexão parâmetros para melhorar o desempenho? Minha cadeia de conexão atual é:

    .

    fonte de dados= batch.db; versão= 3; pooling= true; pool max Tamanho= 10; síncrono= desligado; failifmissing= true; modo de diário= desligado;

  • Eu estou usando o Dapper Orm. (Construído pelos caras do Stackoverflow) Existe uma maneira mais rápida de inserir em massa em SQLite, no .NET?

  • system.data.sqlite está sendo usado para inserir no SQLite. Que tal obter uma versão especial compilada do SQLite que melhora atuação? É uma versão do SQLite melhor que outra? Atualmente usando system.data.sqlite de http://sqlite.phxsoftware.com

  • Atualmente, estou envolvendo inserções dentro de uma transação para torná-los mais rápido (isso fez uma boa melhoria).

  • Estou inserindo em uma tabela de cada vez em 17 tabelas. Eu poderia paralelizar isso em tópicos diferentes e tornar isso mais rápido?

    desempenho atual. Isso é típico? Posso fazer melhor?

    • 55.000 linhas na tabela com 19 colunas: 2,25 seg para inserir (24k insertos / seg)
    • 10.000 linhas na tabela com 63 colunas: 2,74 seg para inserir (3.7k / seg)

      Eu gosto de sqlite, mas eu adoraria torná-lo um pouco mais rápido. Atualmente, salvando meus objetos para um arquivo XML usando a serialização XML é mais rápido do que salvar para um banco de dados SQLite, então meu chefe está perguntando: Por que mudar para SQLite? Ou devo estar usando o MongoDB, ou algum outro banco de dados de objeto?

Foi útil?

Solução

Então eu finalmente encontrei o truque para inserções em massa de alto desempenho no SQLite usando .NET. Este truque melhorou o desempenho de inserção por um fator de 4.1! Meu tempo total de economias passou de 27 segundos para 6,6 segundos. Uau!

Este artigo explica o mais rápido maneira de fazer Bulk insere em sqlite . A chave é reutilizar os mesmos objetos de parâmetros, mas para cada registro para inserir, atribuindo um valor diferente. O tempo que .NET leva construindo todos esses objetos de dbparameter realmente adiciona. Por exemplo, com 100k linhas e 30 colunas= 3 milhões de objetos de parâmetros que devem ser criados. Em vez disso, criar e reutilizar apenas 30 objetos de parâmetros é muito mais rápido.

novo desempenho:

  • 55.000 linhas (19 colunas) em .53 segundos= inserções 100k / segundo

        internal const string PeakResultsInsert = @"INSERT INTO PeakResult values(@Id,@PeakID,@QuanPeakID,@ISTDRetentionTimeDiff)";
    
                var command = cnn.CreateCommand();
                command.CommandText = BatchConstants.PeakResultsInsert;
    
                string[] parameterNames = new[]
                                     {
                                       "@Id",
                                       "@PeakID",
                                       "@QuanPeakID",
                                       "@ISTDRetentionTimeDiff"
                                      };
    
                DbParameter[] parameters = parameterNames.Select(pn =>
                {
                    DbParameter parameter = command.CreateParameter();
                    parameter.ParameterName = pn;
                    command.Parameters.Add(parameter);
                    return parameter;
                }).ToArray();
    
                foreach (var peakResult in peakResults)
                {
                    parameters[0].Value = peakResult.Id;
                    parameters[1].Value = peakResult.PeakID;
                    parameters[2].Value = peakResult.QuanPeakID;
                    parameters[3].Value = peakResult.ISTDRetentionTimeDiff;
    
                    command.ExecuteNonQuery();
                }
    

    Isso acaba que eu não poderia usar Dapper para inserir em minhas tabelas grandes. (Para minhas pequenas mesas, ainda uso Dapper).

    Note, algumas outras coisas que eu encontrei:

    • Eu tentei usar vários threads para inserir dados no mesmo banco de dados, isso não fez nenhuma melhoria. (não fez a diferença)

    • Atualizado de System.data.sqlite 1.0.69 a 1.0.79. (não fez diferença no desempenho que eu podia ver)

    • Eu não estou atribuindo um tipo ao dbparameter, não parece fazer uma diferença de desempenho de qualquer maneira.

    • para leituras, não pude melhorar o desempenho da Dapper.

Outras dicas

.

Atualmente, estou envolvendo inserções dentro de uma transação para fazê-los mais rápido (isso fez uma boa melhoria).

O maior ganho que já vi na velocidade de inserção em massa era quebrar inserções em pedaços menores.Quão pequeno de um pedaço varia por plataforma / esquema / etc, tenho certeza.Eu acredito que durante meus testes foi quase 1000 ou mais.

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