96 votes

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?

  • Existe-il mieux Orm?
    (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.)

  • Une mystérieuse 3ème option qui va m'aider à obtenir plus de vitesse de mon service.

REMARQUE: la Plupart de mes DB d'interactions ou de Créer et de mettre à Jour. Je ne fais que très très peu de sélection et suppression d'.

88voto

Sean Points 311

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. 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"

Se 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 c'est la solution à votre problème.

50voto

J. Tihon Points 3519

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 l' 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:

Product product = db.Products.SingleOrDefault(p => p.Id == 10);
// executes SELECT * FROM Products WHERE Id = 10

ProductDto dto = new ProductDto();
foreach (Category category in product.Categories)
// executes SELECT * FROM Categories WHERE ProductId = 10
{
    dto.Categories.Add(new CategoryDto { Name = category.Name });
}

Pourrait être remplacé par:

var query = from p in db.Products
            where p.Id == 10
            select new
            {
                p.Name,
                Categories = from c in p.Categories select c.Name
            };
ProductDto dto = new ProductDto();
foreach (var categoryName in query.Single().Categories)
// Executes SELECT p.Id, c.Name FROM Products as p, Categories as c WHERE p.Id = 10 AND p.Id = c.ProductId
{
    dto.Categories.Add(new CategoryDto { Name = categoryName });
}

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.

38voto

Steve Wortham Points 11563

Une suggestion est d'utiliser LINQ to Entity Framework uniquement pour enregistrer CRUD consolidés.

Pour plus d'impliquer des requêtes, des recherches, des rapports, etc, écrire une procédure stockée et l'ajouter au modèle d'Entity Framework tel que décrit sur le site 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 l'avez fait, 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.

15voto

JulianR Points 7257

Si vous êtes purement de l'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

6voto

Sean Kearon Points 2670

Vous dites 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 avec aucune 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 ils sont décrits dans les fiches produits du site.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X