Les encarts en vrac prennent 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 exécuté 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();
}

il a fallu environ 20 secondes. C'est 2500 inserts / seconde. Pas mal, mais pas génial non plus, compte tenu que le blog atteignait 45 000 insertions par seconde. Y a-t-il un moyen plus efficace de le faire dans Dapper?

En outre, en exécutant ce code via le débogueur Visual Studio, vous avez pris plus de 3 minutes! Je pensais que le débogueur le ralentirait un peu, mais j'étais vraiment surpris de voir ça.

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