Entity framework problème de performances, saveChanges est très lent
Récemment, je suis une simple EF travail. Très simple,
tout d'abord,
List<Book> books = entity.Books.WHERE(c=>c.processed==false)ToList();
then
foreach(var book in books)
{
//DoSomelogic, update some properties,
book.ISBN = "ISBN " + randomNumber();
book.processed = true;
entity.saveChanges(book)
}
J'ai mis entity.saveChanges
dans le foreach
parce que c'est une grande liste, autour de 100k dossiers, et si cet enregistrement est traitée sans problème, puis le drapeau de ce dossier, l'ensemble du livre.traitées = true, si le processus est interrompu par exception, alors la prochaine fois, je n'ai pas à traiter ces bons enregistrements.
Tout semble ok pour moi. Il est rapide lorsque vous traitez des centaines de dossiers. Puis, quand nous nous déplaçons à 100k enregistrements, d'une entité.saveChanges est très très lent. autour de 1 à 3 secondes par enregistrement. Ensuite, nous gardons le modèle d'entité, mais remplacer entity.saveChanges
classique SqlHelper.ExecuteNonQuery("update_book", sqlparams)
. Et il est très rapide.
Quelqu'un pourrait-il me dire pourquoi entity framework processus qui est lent? Et si je veux encore de l'utilisation de l'entité.saveChanges, quelle est la meilleure manière d'améliorer les performances?
Merci
OriginalL'auteur user454232 | 2014-01-22
Vous devez vous connecter pour publier un commentaire.
Désactiver le suivi des modifications avant d'effectuer vos inserts. Cela permettra d'améliorer vos performances de manière significative (de l'ordre de grandeur de l'ordre). Mettre
SaveChanges()
à l'extérieur de votre boucle de l'aide, mais de désactiver le suivi des modifications aidera encore plus.Voir cette page pour plus d'information.
commettre chaque champ de chaque inséré entité de la base de données. La requête va être plus long, mais sans doute encore plus rapide que la course
DetectChanges
, en particulier pour les insertions.href="https://msdn.microsoft.com/en-us/data/jj556205.aspx" >Microsoft dit ce "peut facilement introduire des bogues subtils dans votre application". Quand je l'ai essayé, il m'a fallu un certain temps à comprendre pourquoi mes mises à jour complètement arrêté de travailler. Quand je l'ai réparé, il n'était pas plus rapide. Je suppose que c'est peut-être utile pour d'autres scénarios.
pas de changement!.. toujours prendre le temps. je suis d'économie de 1200 dossiers à la fois et il est de 24 secondes pour enregistrer.
OriginalL'auteur Steve
Je prendrais le SaveChanges(livre) à l'extérieur de la boucle foreach. Depuis que le livre est sur l'entité dans la liste, vous pouvez mettre ceci à l'extérieur et de l'EF fonctionne mieux avec le code résultant.
La liste est un attribut de l'entité, et EF est conçu pour optimiser les mises à jour/crée/supprime sur l'extrémité arrière de la base de données. Si vous faites cela, je serais curieux de savoir si ça aide.
C'est une bonne réflexion, mais Entity Framework peut gérer mieux dans l'autre sens. Entity Framework a la possibilité d'optimiser les mises à jour et des inserts. Elle tend aussi à essayer plein de validation sur l'ensemble de l'enregistrement lorsque savechanges() est placé à l'intérieur d'une boucle comme celle que vous avez posté.
OriginalL'auteur Kyland Holmes
Moi aussi, je peut vous conseiller de prendre le SaveChanges() de la boucle, comme c'est le 'n' le nombre de mises à jour de la base de données, ainsi que le contexte aura de " n " fois l'itération à travers les points de contrôle et les validations nécessaires.
OriginalL'auteur Dani Mathew
"AsNoTracking" fonctionne pour moi
ex:
Sans "AsNoTracking" les mises à jour est très lent.
OriginalL'auteur Paulo
Le Cadre de l'Entité, à mon avis, est un mauvais choix pour les opérations en bloc à la fois à partir d'une performance et une consommation de mémoire de point de vue. Une fois que vous obtenez au-delà de quelques milliers d'enregistrements, la méthode SaveChanges commence vraiment à se décomposer.
Vous pouvez essayer de partitionner votre travail de plus en plus petites transactions, mais encore une fois, je pense que vous travaillez trop dur pour créer cette.
Une bien meilleure approche est de mettre à profit l'essentiel des opérations qui sont déjà fournis par votre SGBD. SQL Server fournit la COPIE en bloc via .NET. Oracle fournit la COPIE en bloc pour l'Oracle.DataAccess ou de données non l'accès. Pour Oracle.ManagedDataAccess, la COPIE en bloc de la bibliothèque malheureusement n'est pas disponible. Mais je peux créer une Procédure Stockée Oracle à l'aide de BULK COLLECT/POUR TOUT ce qui me permet d'insérer des milliers de dossiers en quelques secondes, avec une plus faible empreinte mémoire au sein de votre application. Au sein de la .NET application, vous pouvez mettre en œuvre PLSQL, les tableaux Associatifs en tant que paramètres, etc.
L'avantage de tirer parti de la majeure partie des installations à l'intérieur de votre SGBD est de réduire les changements de contexte entre votre application, le processeur de requête et de la base de données du moteur.
Je suis sûr que d'autres fournisseurs de bases de fournir quelque chose de similaire.
OriginalL'auteur Charles Owen