Linq to entities - une VS Premier VS Existe
Je suis en utilisant Entity Framework et j'ai besoin de vérifier si un produit avec un nom = "xyz" existe ...
Je pense que je peux utiliser n'Importe quel(), il Existe() ou (Premier).
Laquelle est la meilleure option pour ce genre de situation? Qui a le meilleur rendement?
Merci,
Miguel
OriginalL'auteur Miguel Moura | 2012-09-14
Vous devez vous connecter pour publier un commentaire.
Tout se traduit par "Existe" au niveau base de données. La première se traduit par Select Top 1 ... Entre ceux-ci, Existe à effectuer d'Abord parce que l'objet n'a pas besoin d'être récupérée, seulement un résultat Booléen de la valeur.
À moins que vous ne demandez pas à ce sujet .Où(x => x.Count() > 0), ce qui implique l'ensemble du match pour être évaluées et itéré avant que vous pouvez déterminer ce que vous avez un enregistrement. Tout court-circuits à la demande et peuvent être beaucoup plus rapides.
.Any()
est plus simple, et il sera mieux que le.Where(x => x.Count > 0)
, il devrait donc être préféré.il est vrai que le comptage est fait dans la bd, mais c'est encore pire que de les compter, grâce à EF est horrible de génération de requête. Voir ma réponse.
OriginalL'auteur Jim Wooley
Bon, je n'allais pas à peser sur le présent, mais Diego réponse complique les choses que je pense que des explications supplémentaires est dans l'ordre.
Dans la plupart des cas,
.Any()
sera plus rapide. Voici quelques exemples.Dans les deux exemples ci-dessus, Entity Framework génère une requête optimal. Le
.Any()
appel fait partie d'un prédicat, et Entity Framework gère ce bien. Cependant, si nous faisons le résultat de.Any()
partie de l'ensemble de résultats comme ceci:... soudain Cadre de l'Entité décide de créer deux versions de la condition, de sorte que la requête n'a autant que deux fois plus de travail qu'il en a vraiment besoin pour. Toutefois, la requête suivante n'est pas mieux:
Compte tenu de la requête ci-dessus, Entity Framework va encore créer deux versions de la condition, plus il faudra également SQL Server pour effectuer un nombre réel, ce qui signifie qu'il ne reçoit pas de court-circuit dès qu'il trouve un élément.
Mais si vous êtes juste de la comparaison de ces deux requêtes:
Activities.Any(a => a.Title == "xyz")
Activities.Count(a => a.Title == "xyz") > 0
... qui sera le plus rapide? Il dépend.
La première requête produit de l'inefficacité d'un double condition de la requête, ce qui signifie qu'il faudra jusqu'à deux fois plus longtemps qu'elle a à.
La deuxième requête forces de la base de données pour vérifier chaque élément de la table sans court-circuit, ce qui signifie qu'il pourrait prendre jusqu'à
N
fois plus qu'il n'a, selon le nombre d'éléments doivent être évalués avant de trouver un match. Supposons que la table a 10 000 éléments:Title
et des colonnes de clé, cette requête à peu près la moitié du temps que la première requête.Donc en résumé, SI vous êtes:
Entity Framework 4 (depuis les versions plus récentes peuvent améliorer la structure de la requête)Entity Framework 6.1 ou une version antérieure (depuis 6.1.1 a un correctif pour améliorer la requête), ETALORS vous pouvez vous attendre
.Any()
à prendre jusqu'à deux fois plus longtemps que.Count()
. Par exemple, une requête peut prendre 100 millisecondes au lieu de 50. Ou 10 au lieu de 5.DANS TOUTE AUTRE CIRCONSTANCE
.Any()
devrait être au moins aussi rapide, et éventuellement ordres de grandeur plus rapide que.Count()
.Indépendamment, jusqu'à ce que vous avez déterminé que c'est en fait la source de la mauvaise performance de votre produit, vous devez vous soucier plus sur ce qui est facile à comprendre.
.Any()
plus clairement et de façon concise ce que vous êtes vraiment essayer de comprendre, de sorte bâton avec qui.Count() > 0
, je voudrais utiliserFirstOrDefault() != null
.Une idée intéressante. Mais je l'ai testé, et qui crée une encore plus fou de la requête, avec deux à l'extérieur-applique les instructions select. Donc, il ne fait pas de résoudre le problème, et il rend le code (à mon avis) un peu moins clair.
+1 pour le "si vous avez déterminé que c'est en fait la source de la mauvaise performance de votre produit, vous devez vous soucier plus sur ce qui est facile à comprendre." commentaire
EF 6.1.1 a un correctif pour
Any()
la création d'unCASE
avec 2EXISTS
clauses. Voir WI 192.Vous pouvez éliminer le double existe en procédant comme ceci: les flux de travail.Sélectionnez(w => w.Les activités.(A => un.Titre == "xyz") ? vrai : faux). (cela a été fait il y a longtemps, les comportements ont changé dans les versions récentes de l'EF).
OriginalL'auteur StriplingWarrior
On pourrait penser
Any()
donne de meilleurs résultats, car il se traduit par uneEXISTS
requête... mais EF est terriblement cassé, la génération de ce (édité):Au lieu de:
...en fait doubler le coût d'une requête (pour les requêtes simples; c'est encore pire pour les complexes)
J'ai trouvé à l'aide de
.Count(condition) > 0
est plus rapide à peu près toujours (le coût est exactement le même comme un bien écritEXISTS
requête)OriginalL'auteur Diego Mijelshon
Any()
etFirst()
est utilisé avecIEnumerable
qui vous donne la souplesse nécessaire pour évaluer les choses tranquillement. CependantExists()
exige de la Liste.J'espère que cela efface les choses pour vous et vous aider à décider lequel utiliser.
OriginalL'auteur Tabish