Inserts en vrac prenant plus de temps que prévu avec Dapper

dapper performance sqlbulkcopy

Question

Après avoir lu cet article, j’ai décidé de regarder de plus près la façon dont j’utilisais Dapper.

J'ai couru ce code sur une base de données vide

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();
}

cela a pris environ 20 secondes. C'est 2500 inserts / seconde. Pas mal, mais pas génial non plus, vu que le blog atteignait 45k inserts / seconde. Existe-t-il un moyen plus efficace de faire cela dans Dapper?

En outre, l’exécution de ce code par le débogueur Visual Studio a pris plus de 3 minutes! Je pensais que le débogueur ralentirait un peu, mais j'étais vraiment surpris de voir cela.

METTRE À JOUR

Donc ça

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

    scope.Complete();
}

et ça

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

les deux ont pris 20 secondes.

Mais cela a pris 4 secondes!

SqlTransaction trans = connection.BeginTransaction();

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

trans.Commit();

Réponse acceptée

Le meilleur que j'ai pu obtenir était de 50 000 enregistrements en 4 secondes grâce à cette approche

SqlTransaction trans = connection.BeginTransaction();

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

trans.Commit();

Réponse d'expert

L'utilisation de la méthode Execute avec une seule instruction d'insertion ne permet jamais d'insérer en bloc ou d'être efficace. Même la réponse acceptée avec une Transaction ne fait pas d' Bulk Insert .

Si vous souhaitez effectuer une Bulk Insert SqlBulkCopy , utilisez le SqlBulkCopy https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy

Vous ne trouverez rien de plus rapide que cela.

Dapper Plus

Disclaimer : Je suis le propriétaire du projet Dapper Plus

Ce projet n'est pas gratuit mais offre toutes les opérations en vrac:

  • BulkInsert
  • BulkUpdate
  • BulkDelete
  • BulkMerge

(Utiliser sous le capot SqlBulkCopy )

Et quelques options supplémentaires telles que la sortie de valeurs d'identité:

// 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);   

Notre bibliothèque prend en charge plusieurs fournisseurs:

  • serveur SQL
  • SQL Compact
  • Oracle
  • MySql
  • PostgreSQL
  • SQLite
  • Oiseau de feu


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi