Las inserciones a granel tardan más de lo esperado usando Dapper

dapper performance sqlbulkcopy

Pregunta

Después de leer este artículo , decidí echar un vistazo más de cerca a la forma en que estaba usando Dapper.

Corrí este código en una base de datos vacía

var members = new List<Member>();
for (int i = 0; i < 50000; i++)
{
    members.Add(new Member()
    {
        Username = i.toString(),
        IsActive = true
    });
}

using (var scope = new TransactionScope())
{
    connection.Execute(@"
insert Member(Username, IsActive)
values(@Username, @IsActive)", members);

    scope.Complete();
}

Tomó unos 20 segundos. Eso es 2500 inserciones / segundo. No está mal, pero tampoco excelente, ya que el blog estaba logrando 45k inserciones / segundo. ¿Hay una manera más eficiente de hacer esto en Dapper?

Además, como nota al margen, ¡ejecutar este código a través del depurador de Visual Studio tomó más de 3 minutos! Pensé que el depurador lo reduciría un poco, pero realmente me sorprendió ver eso.

ACTUALIZAR

Así que esto

using (var scope = new TransactionScope())
{
    connection.Execute(@"
insert Member(Username, IsActive)
values(@Username, @IsActive)", members);

    scope.Complete();
}

y esto

    connection.Execute(@"
insert Member(Username, IsActive)
values(@Username, @IsActive)", members);

ambos tardaron 20 segundos.

¡Pero esto tomó 4 segundos!

SqlTransaction trans = connection.BeginTransaction();

connection.Execute(@"
insert Member(Username, IsActive)
values(@Username, @IsActive)", members, transaction: trans);

trans.Commit();

Respuesta aceptada

Lo mejor que pude lograr fue 50k registros en 4 segundos usando este enfoque

SqlTransaction trans = connection.BeginTransaction();

connection.Execute(@"
insert Member(Username, IsActive)
values(@Username, @IsActive)", members, transaction: trans);

trans.Commit();

Respuesta experta

El uso del método Execute con solo una instrucción de inserción nunca hará una inserción masiva o será eficiente. Incluso la respuesta aceptada con una Transaction no hace una Bulk Insert .

Si desea realizar una Bulk Insert , use SqlBulkCopy https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy

No encontrarás nada más rápido que esto.

Dapper Plus

Descargo de responsabilidad : soy el propietario del proyecto Dapper Plus

Este proyecto no es gratuito, pero ofrece todas las operaciones a granel:

  • BulkInsert
  • Actualización masiva
  • BulkDelete
  • BulkMerge

(Usar debajo del capó SqlBulkCopy )

Y algunas opciones más, como la salida de valores de identidad:

// CONFIGURE & MAP entity
DapperPlusManager.Entity<Order>()
                 .Table("Orders")
                 .Identity(x => x.ID);

// CHAIN & SAVE entity
connection.BulkInsert(orders)
          .AlsoInsert(order => order.Items);
          .Include(x => x.ThenMerge(order => order.Invoice)
                         .AlsoMerge(invoice => invoice.Items))
          .AlsoMerge(x => x.ShippingAddress);   

Nuestra biblioteca admite múltiples proveedores:

  • servidor SQL
  • SQL Compact
  • Oráculo
  • MySql
  • PostgreSQL
  • SQLite
  • Firebird


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué