Pregunta

Estoy trabajando en una aplicación de escritorio que utiliza SQLite para insertar a granel decenas de miles de filas en una base de datos SQLite. Me gustaría ayudar a optimizar el rendimiento de inserción a granel. Actualmente toma hasta 50 segundos para insertar 60 megs de datos en la base de datos.

  • ¿Qué parámetros de cadena de conexión podrían usar para mejorar ¿rendimiento? ¿Debo cambiar el tamaño del búfer? Es esto posible a través de un ¿Parámetro de cadena de conexión? ¿Hay alguna otra cadena de conexión? ¿Parámetros para mejorar el rendimiento? Mi cadena de conexión actual es:

    fuente de datos= batch.db; versión= 3; agrupación= verdadero; piscina máxima Tamaño= 10; síncrono= apagado; Failifmissing= verdadero; modo de diario= apagado;

  • Estoy usando DAPPER ORM. (construido por los chicos en StackOverflow) ¿Hay una manera más rápida de insertar a granel en SQLite, en .NET?

  • system.data.sqlite se está utilizando para insertar en SQLite. ¿Qué pasa con obtener una versión compilada especial de SQLite que mejora? ¿rendimiento? ¿Es una versión de SQLite mejor que otra? Actualmente usando system.data.sqlite desde http://sqlite.phxsoftware.com

  • Actualmente, estoy envolviendo inserciones dentro de una transacción para hacerlas más rápido (esto hizo una buena mejora).

  • Estoy insertando en una mesa en un momento en 17 mesas. ¿Podría paralelizar esto en diferentes hilos y hacer esto más rápido?

    Actuación actual. ¿Es esto típico? ¿Puedo hacerlo mejor?

    • 55,000 filas en la mesa con 19 columnas: 2.25 segundos para insertar (inserciones 24k / seg)
    • 10,000 filas en mesa con 63 columnas: 2.74 segundos para insertar (3.7k / seg)

      Me gusta SQLite, pero me encantaría hacerlo un poco más rápido. Actualmente, guardar mis objetos a un archivo XML utilizando la serialización XML es más rápida que ahorrar en una base de datos SQLite, por lo que mi jefe está preguntando: ¿Por qué cambiar a SQLite? ¿O debería estar usando MongoDB, o alguna otra base de datos de objetos?

¿Fue útil?

Solución

Así que finalmente encontré el truco a los insertos a granel de alto rendimiento en SQLite usando .NET. ¡Este truco mejoró el rendimiento de inserto por un factor de 4.1! Mi tiempo de ahorro total pasó de 27 segundos a 6.6 segundos. ¡Guau!

Este artículo explica el la forma más rápida de hacer inserciones a granel en sqlite . La clave está reutilizando los mismos objetos de parámetros, pero para cada registro para insertar, asignando un valor diferente. El tiempo que .NET toma construir todos los objetos DBParameter realmente se suma. Por ejemplo, con filas de 100k y 30 columnas= 3 millones de objetos de parámetros que deben ser creados. En su lugar, crear y reutilizar solo 30 objetos de parámetros es mucho más rápido.

Nuevo rendimiento:

  • 55,000 filas (19 columnas) en .53 segundos= 100k insertos / 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();
                }
    

    termina que no pude usar dapper para insertar en mis tablas grandes. (Para mis pequeñas mesas, todavía uso Dapper).

    Nota, algunas otras cosas que encontré:

    • Intenté usar múltiples hilos para insertar datos en la misma base de datos, esto no hizo ninguna mejora. (no hice una diferencia)

    • actualizado desde system.data.sqlite 1.0.69 a 1.0.79. (No hizo una diferencia en el rendimiento que podía ver)

    • No estoy asignando un tipo al DBParameter, no parece hacer una diferencia de rendimiento de cualquier manera.

    • Para las lecturas, no pude mejorar el rendimiento de Dapper.

Otros consejos

Actualmente, estoy envolviendo insertos dentro de una transacción para hacerlos más rápido (esto hizo una buena mejora).

La mayor ganancia que he visto en la velocidad de inserción a granel fue romper las inserciones en trozos más pequeños.¿Qué tan pequeño varía un trozo por plataforma / esquema / etc, estoy seguro?Creo que durante mis pruebas estaba cerca de 1000 más o menos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top