Entity Framework est Trop Lent. Quelles sont mes options?
J'ai suivi le "Ne pas Optimiser Prématurément" mantra et codé mon Service WCF à l'aide de Entity Framework.
Cependant, j'ai dressé le portrait de la performance et Entity Framework est trop lent. (Mon app processus de 2 messages dans environ 1,2 secondes, où l' (héritage) app que je suis re-écriture ne 5-6 messages en même temps. (L'héritage appels app sprocs pour son DB Access).
Mon profilage des points à l'Entité Cadre de la prise de la majeure partie du temps par message.
Alors, quelles sont mes options?
-
Sont là, mieux Orm là?
(Quelque chose qui prend en charge normale de la lecture et de l'écriture des objets et il le fait vite..) -
Est-il un moyen de faire de l'Entité Cadre plus vite?
(Note: quand je dis que plus vite je veux dire sur le long terme, pas le premier appel. (Le premier appel est lente (15 secondes d'un message), mais ce n'est pas un problème. J'ai juste besoin d'être rapide pour le reste des messages.) -
De mystérieux 3ème option qui va m'aider à obtenir plus de vitesse de mon service.
REMARQUE: la Plupart de mes DB interactions sont de Créer et de mettre à Jour. Je ne fais que très très peu de sélection et suppression d'.
- Cela sonne comme une resucée de "linq est lent" comment savez-vous qu'il est EF? Avez-vous profilé toutes vos modifications?
- Certaines réponses sont pointant vers les requêtes. Dans mon expérience, la lenteur dans l'EF a peu à voir avec les requêtes, mais avec les coûts de réalisation, et que ces coûts sont souvent liés à la modification de suivi et comment cela influe sur l'instance(s) de création. Malheureusement, je n'ai pas de solution miracle pour vous donc c'est juste un commentaire, mais je vous recommande de voir si le profilage révèle haute matérialisation des coûts et, le cas échéant, de la recherche de ce qui peut être fait au sujet de ces coûts.
- J'ai pensé que j'ai indiqué que j'avais profilé et trouvé que c'était EF/DB qui était lent. De toute façon, oui je l'ai fait. Je profilé et il est EF/DB interactions qui sont les principaux coupables.
- N'est-ce pas la matérialisation de la première exécution genre de choses? Si oui, vous avez raison, il est très lent. La première manche est super lent. Mais comme je l'ai indiqué, je ne suis pas trop inquiet à ce sujet. C'est le débit total qui est le problème. (Si ce n'est pas ce Matérialisation est que j'ai besoin donc quelques recherches pour voir si c'est la cause de mon problème)
- non, la matérialisation est le processus de prise de données à partir de la base de données et l'instanciation et de remplir le graphe d'objets pour représenter ces données. Je ne parle pas de la première exécution de la performance, comme le code est jitted (ou même comme Sql Server peut créer le plan d'exécution de requête), mais ce qui se passe à chaque fois que vous obtenir les données sous forme d'objets.
- Je vais regarder dans le. Peut-être il ya un moyen à la vitesse maximum.
- J'aimerais vraiment vous recommander d'aller dans les détails ce qu'est exactement le code que vous écrivez pour insérer et mettre à jour des entités (de préférence dans une nouvelle question d'équité pour les personnes qui ont déjà répondu à votre question en cours) avant que vous pensez de mesures radicales comme le changement de l'ORM. Vous ne dites pas quelle est la version de EF vous utilisez, si vous utilisez POCOs, si vous utilisez des proxies dynamiques, si vous avez la détection automatique des changements activé, etc. J'ai vu dans ma propre insérer/mettre à jour le code différences de performances par un facteur 50 (= cinquante) selon sur de tels détails.
- Quelques liens à propos de ce que je veux dire avec mon commentaire précédent: 1) stackoverflow.com/q/5943394/270591 2) stackoverflow.com/q/5917478/270591 3) stackoverflow.com/q/5940225/270591, 4) stackoverflow.com/q/5798646/270591. Aucun d'entre eux ou de la totalité d'entre eux pourraient être applicables à votre situation. Il dépend seulement sur les détails de vos paramètres et votre code.
- Entity Framework est beaucoup plus rapide dans le .net 4.5 outofmemory.co.royaume-uni/...
- pour les premières, il est plus rapide... Pas beaucoup est fait pour que la normal "au milieu de l'app" de traitement.
- Entity Framework est lent? Je ne pense pas. Stackoverflow est de travailler la preuve. Si il y a un problème avec EF avoir anormale de la latence c'est avec le développeur. Simple que cela.
- Je suis impliqué avec une grande application à l'aide de EF et les requêtes SQL qu'il génère peut être très lent. Je ne dis pas de ne pas l'utiliser, mais être préparé à l'étape et utiliser des procédures stockées lorsque vous avez des problèmes. Les procédures stockées peuvent encore être appelé à partir d'EF et vous ne pouvez pas encore de test de l'unité et de l'utilisation d'un modèle de référentiel etc Cela suppose que vous avez confirmé le SQL est le problème.
- EF a été vraiment conçu pour être flexible avec toute source de données et qui est son plus grand pouvoir, cependant, si vous êtes toujours à l'aide de MS-SQL, il n'y a pas beaucoup de point à ne pas utiliser des procédures stockées w/EF (et, peut-être, ne pas utiliser EF - comme il ajoute certainement la plus "qu'est ce qu'il fait maintenant?" des questions dans le processus de développement). Si vous détestez l'obfuscation ou besoin d'amende à l'écoute de contrôle, EF n'est pas pour vous. Sur vraiment de projets complexes EF, honnêtement, prend plus de temps à déboguer, en général (et plus facile à frire d'une base de données!).
Vous devez vous connecter pour publier un commentaire.
Vous devriez commencer par le profilage de l'commandes SQL émis par l'Entity Framework. En fonction de votre configuration (POCO, entités Self-Tracking) il y a beaucoup de place pour les optimisations. Vous pouvez déboguer les commandes SQL (ce qui ne devrait pas différer entre debug et release mode) à l'aide de la
ObjectSet<T>.ToTraceString()
méthode. Si vous rencontrez une requête qui nécessite la poursuite de l'optimisation, vous pouvez utiliser certains des projections de donner EF de plus amples renseignements au sujet de ce que vous essayez d'accomplir.Exemple:
Pourrait être remplacé par:
J'ai tapé juste que hors de ma tête, donc ce n'est pas exactement la façon dont il va être exécuté, mais EF en fait quelques belles optimisations si vous le dites tout ce que vous savez à propos de la requête (dans ce cas, que nous aurons besoin de la catégorie des noms). Mais ce n'est pas comme désireux de chargement (db.Produits.Include("Catégories")), car les projections peuvent réduire davantage la quantité de données à charger.
Le fait de la question est que les produits comme le Cadre de l'Entité sera TOUJOURS lent et inefficace, parce qu'ils sont en cours d'exécution beaucoup plus de code.
Je trouve aussi idiot que les gens sont ce qui suggère que l'on doit optimiser les requêtes LINQ, regardez le SQL généré, l'utilisation des débogueurs, des pré-compiler, de prendre de nombreuses mesures supplémentaires, etc. c'est à dire de perdre beaucoup de temps. Personne ne dit - Simplifier! Tout le monde veut comlicate les choses plus loin en prenant encore plus d'étapes (de perdre du temps).
Une approche de bon sens serait de ne pas utiliser EF ou LINQ à tous. Utiliser du SQL. Il n'y a rien de mal à cela. Juste parce qu'il ya mentalité de troupeau parmi les programmeurs et ils se sentent l'envie d'utiliser chaque nouveau produit sur le marché, ne signifie pas qu'il est bon ou il va travailler. La plupart des programmeurs pense que si ils intègrent chaque nouveau morceau de code publié par une grande entreprise, c'est d'en faire un plus intelligente programmeur; pas vrai du tout. Programmation intelligente est surtout sur la façon de faire plus avec moins de maux de tête, des incertitudes, et dans le minimum de temps. Rappelez - Temps! C'est l'élément le plus important, alors essayez de trouver des moyens de ne pas la gaspiller sur la résolution de problèmes dans bad/ballonnement du code écrit simplement pour se conformer à certaines étrange, alors appelé "patrons"
Vous détendre, profiter de la vie, de prendre une pause de codage et de cesser d'utiliser des fonctions supplémentaires, du code, des produits, des "patrons". La vie est courte et la durée de vie de votre code est encore plus courte, et il n'est certainement pas la science de fusée. Enlever des couches telles que LINQ, EF et les autres, et votre code sera exécuté de manière efficace, à l'échelle, et oui, il sera toujours facile à maintenir. Trop d'abstraction est une mauvaise "pattern".
Et qui est la solution à votre problème.
Une suggestion est d'utiliser LINQ to Entity Framework uniquement pour enregistrer CRUD consolidés.
Pour impliquer davantage les requêtes, les recherches, les rapports, etc, écrire une procédure stockée et l'ajouter au modèle d'Entity Framework tel que décrit sur MSDN.
C'est l'approche que j'ai pris avec un couple de mes sites et il semble être un bon compromis entre la productivité et la performance. Entity Framework ne sera pas toujours générer le plus efficace SQL pour la tâche à portée de main. Et plutôt que de passer du temps à comprendre pourquoi, l'écriture d'une procédure stockée pour des requêtes plus complexes en réalité gain de temps pour moi. Une fois que vous êtes familier avec le processus, il n'est pas trop de soucis pour ajouter stockées procs pour votre modèle EF. Et bien sûr, l'avantage de l'ajouter à votre modèle est que vous obtenez tout ce qui a fortement tapé bonté qui vient de l'utilisation d'un ORM.
Si vous êtes purement, extraction de données, il est d'une grande aide pour les performances lorsque vous dites EF de ne pas garder la trace des entités qu'elle récupère. Le faire en utilisant MergeOption.NoTracking. EF juste de générer la requête, de l'exécuter et de désérialiser les résultats à des objets, mais de ne pas tenter de suivre les changements de l'entité ou de quelque nature que ce soit. Si une requête est simple (ne pas passer beaucoup de temps d'attente sur la base de données de retour), j'ai trouvé que la mise à NoTracking peut doubler les performances des requêtes.
Voir cet article MSDN sur le MergeOption enum:
La Résolution d'identité, de Gestion de l'État, et le Suivi des modifications
Cela semble être un bon article sur EF performance:
La Performance et l'Entity Framework
Vous dire que vous avez présenté la demande. Avez-vous dressé le portrait de la moraine d'oak ridges trop? Il y a un EF profiler à partir de Ayende, qui mettra en lumière où vous pouvez optimiser votre EF code. Vous pouvez le trouver ici:
http://efprof.com/
N'oubliez pas que vous pouvez utiliser une traditionnelle SQL approche aux côtés de l'ORM si vous avez besoin de gain de performance.
Si il y a une plus/mieux ORM? En fonction de votre objet, modèle de données, vous pourriez envisager d'utiliser un micro-Orm, comme Dapper, Massive ou PetaPoco.
La Dapper site publie quelques comparée des indices de référence qui vous donnera une idée de comment ils se comparent à d'autres Orm. Mais il est intéressant de noter que le micro-Orm ne prennent pas en charge le riche ensemble de fonctionnalités de la pleine Orm comme EF et NH.
Vous pouvez prendre un coup d'oeil à RavenDB. C'est une base de données non relationnelle (à partir de Ayende encore) qui vous permet de stocker POCOs directement sans la cartographie nécessaire. RavenDB est optimisé pour la lecture et rend la vie des développeurs un ensemble beaucoup plus facile en supprimant le besoin de manipuler de schéma et de cartographier vos objets dans le schéma. Cependant, être conscient que c'est nettement une approche différente de l'utilisation d'un ORM approche et elles sont présentées dans la produit site.
J'ai trouvé la réponse par @Slauma ici très utile pour accélérer les choses. J'ai utilisé le même type de modèle pour les deux insertions et mises à jour - et de la performance en flèche.
De mon expérience, le problème non pas avec EF, mais avec ORM approche elle-même.
En général tous les Orm souffre de N+1 problème pas de requêtes optimisées et etc. Ma meilleure supposition serait de traquer les requêtes qui entraîne une dégradation des performances et d'essayer de tune-up outil ORM, ou de réécrire que les parties à la procédure stockée.
C'est simple, non-cadre, non-ORM option qui charge à 10 000/seconde avec 30 champs ou donc. En cours d'exécution sur un vieux portable, et donc probablement plus rapide que dans un environnement réel.
https://sourceforge.net/projects/dopersistence/?source=directory
Je suis tombé sur cette question. J'ai hate de vidage sur EF parce qu'il fonctionne si bien, mais c'est juste lent. Dans la plupart des cas, je veux juste trouver un enregistrement ou de mise à jour/insert. Même de simples opérations de ce genre sont lents. J'ai reculé 1100 enregistrements d'une table dans une Liste et que l'opération a 6 secondes avec EF. Pour moi, c'est trop long, parfois même de sauver prend trop de temps.
J'ai fini par faire mon propre ORM. J'ai tiré les mêmes 1100 enregistrements à partir d'une base de données et mon ORM a pris 2 secondes, beaucoup plus rapide que l'EF. Le tout avec mon ORM est presque instantanée. La seule limitation est que, actuellement, il ne fonctionne qu'avec MS SQL Server, mais il pourrait être modifié pour fonctionner avec d'autres comme Oracle. J'utilise MS SQL Server pour tout maintenant.
Si vous souhaitez essayer mon ORM voici le lien et le site web:
https://github.com/jdemeuse1204/OR-M-Data-Entities
Ou si vous souhaitez utiliser pépite:
H> Install-Package OU-M_DataEntities
La Documentation est sur, il y a l'
Il n'a de sens que pour optimiser fois que vous avez défini. Si vous trouvez que le DB d'accès est lent, vous pouvez les convertir à l'aide de procédures stockées et de garder EF. Si vous trouvez que c'est l'EF lui-même qui est lent, vous pourriez avoir à passer à un autre ORM ou de ne pas utiliser un ORM à tous.
Nous avons une application similaire (Wcf -> EF -> base de données) qui n'120 Requêtes par seconde facilement, donc je suis plus que certain que EF est pas votre problème ici, cela étant dit, j'ai vu de grandes améliorations de performances avec les requêtes compilées.
J'ai utilisé EF, LINQ to SQL et pimpant. Dapper est le plus rapide.
Exemple: j'ai besoin de 1000 principaux dossiers avec 4 sous-dossiers de chaque. J'ai utilisé LINQ to sql, il a fallu environ 6 secondes. J'ai ensuite passé à dapper, consulté le 2 ensembles d'enregistrements à partir de la seule procédure stockée et pour chaque enregistrement ajouté les sous-dossiers. Temps Total 1 seconde.
Également la procédure stockée utilisée valeur de la table de fonctions avec la croix appliquer, j'ai trouvé la valeur scalaire de fonctions très lent.
Mon conseil serait d'utiliser EF ou LINQ to SQL et pour certaines situations, commutateur de dapper.
Le Cadre de l'Entité ne doit pas provoquer d'importants goulots d'étranglement de lui-même. Les Chances sont qu'il existe d'autres causes. Vous pourriez essayer de basculer EF Linq2SQL, les deux ont en comparant les caractéristiques et le code doit être facile à convertir, mais dans de nombreux cas, Linq2SQL est plus rapide que l'EF.