Im System.Linq
Namespace können wir jetzt unsere IEnumerables um die Erweiterungsmethoden Any () und Count () erweitern .
Mir wurde kürzlich gesagt, dass ich, wenn ich überprüfen möchte, ob eine Sammlung 1 oder mehr Elemente enthält, die .Any()
Erweiterungsmethode anstelle der .Count() > 0
Erweiterungsmethode verwenden sollte, da die .Count()
Erweiterungsmethode alle Elemente durchlaufen muss.
Zweitens haben einige Sammlungen eine Eigenschaft (keine Erweiterungsmethode), die Count
oder ist Length
. Wäre es besser, diese anstelle von .Any()
oder zu verwenden .Count()
?
ja / nae?
.net
linq
performance
.net-3.5
extension-methods
Pure.Krome
quelle
quelle
Antworten:
Wenn Sie mit etwas beginnen , das eine hat
.Length
oder.Count
(wieICollection<T>
,IList<T>
,List<T>
usw.) - dann wird dies die schnellste Option sein, da sie nicht durch das gehen mussGetEnumerator()
/MoveNext()
/Dispose()
Sequenz erforderlichAny()
für eine nicht-leer überprüfenIEnumerable<T>
Sequenz .Denn nur
IEnumerable<T>
dannAny()
wird es in der Regel schneller gehen, da nur eine Iteration betrachtet werden muss. Beachten Sie jedoch, dass die LINQ-to-Objects-Implementierung vonCount()
prüftICollection<T>
(.Count
als Optimierung verwendet). Wenn Ihre zugrunde liegende Datenquelle also direkt eine Liste / Sammlung ist, gibt es keinen großen Unterschied. Fragen Sie mich nicht, warum das nicht generische nicht verwendet wirdICollection
...Wenn Sie LINQ zum Filtern usw. (
Where
usw.) verwendet haben, haben Sie natürlich eine iteratorblockbasierte Sequenz, sodass dieseICollection<T>
Optimierung unbrauchbar ist.Im Allgemeinen mit
IEnumerable<T>
:Any()
bleib bei ;-pquelle
(somecollection.Count > 0)
? War unser gesamter Code vor der Einführung der .Any () -Methode von LINQ schwer zu verstehen?someCollection.Count > 0
genauso klar ist wiesomeCollection.Any()
der zusätzliche Vorteil einer höheren Leistung und der Tatsache, dass kein LINQ erforderlich ist. Zugegeben, dies ist ein sehr einfacher Fall, und andere Konstrukte, die LINQ-Operatoren verwenden, vermitteln die Absicht der Entwickler viel klarer als die entsprechende Nicht-LINQ-Option.Hinweis: Ich habe diese Antwort geschrieben, als Entity Framework 4 aktuell war. Der Sinn dieser Antwort war nicht in trivial zu bekommen
.Any()
vs.Count()
Performance - Tests. Es ging darum zu signalisieren, dass EF alles andere als perfekt ist. Neuere Versionen sind besser ... aber wenn Sie einen Teil des Codes haben, der langsam ist und EF verwendet, testen Sie mit direktem TSQL und vergleichen Sie die Leistung, anstatt sich auf Annahmen zu verlassen (das.Any()
ist IMMER schneller als.Count() > 0
).Obwohl ich mit den meisten Antworten und Kommentaren einverstanden bin - insbesondere in Bezug auf den Punkt
Any
, der die Absicht des Entwicklers besser signalisiert alsCount() > 0
-, hatte ich eine Situation, in der Count auf SQL Server (EntityFramework 4) um eine Größenordnung schneller ist.Hier ist eine Abfrage mit
Any
dieser Ausnahme des Timeouts (bei ~ 200.000 Datensätzen):Count
Version in Millisekunden ausgeführt:Ich muss einen Weg finden, um zu sehen, welches genaue SQL beide LINQs produzieren - aber es ist offensichtlich, dass zwischen
Count
undAny
in einigen Fällen ein großer Leistungsunterschied besteht , und leider scheint es, dass Sie nichtAny
in allen Fällen einfach bleiben können.EDIT: Hier werden SQLs generiert. Schönheiten wie du sehen kannst;)
ANY
::COUNT
::Scheint, dass reines Where with EXISTS viel schlechter funktioniert als das Berechnen von Count und dann Where with Count == 0.
Lassen Sie mich wissen, wenn Sie einen Fehler in meinen Ergebnissen sehen. Was aus all dem herausgenommen werden kann, ist, dass komplexere LINQ viel besser dran sind, wenn sie als gespeicherte Prozedur umgeschrieben werden;).
quelle
Da dies ein ziemlich beliebtes Thema ist und die Antworten unterschiedlich sind, musste ich das Problem neu betrachten.
Testen von env: EF 6.1.3, SQL Server, 300.000 Datensätze
Tabellenmodell :
Testcode:
Ergebnisse:
Beliebig () ~ 3ms
Count () ~ 230 ms für die erste Abfrage, ~ 400 ms für die zweite
Bemerkungen:
In meinem Fall hat EF kein SQL generiert, wie in seinem Beitrag @Ben erwähnt.
quelle
Count() > 0
. : DBEARBEITEN: Es wurde in EF Version 6.1.1 behoben. und diese Antwort ist nicht mehr aktuell
Bei SQL Server und EF4-6 ist Count () etwa doppelt so schnell wie Any ().
Wenn Sie Table.Any () ausführen, wird so etwas wie ( Warnung: Verletzen Sie nicht das Gehirn, das versucht, es zu verstehen ) generiert.
Das erfordert 2 Scans von Zeilen mit Ihrem Zustand.
Ich schreibe nicht gern,
Count() > 0
weil es meine Absicht verbirgt. Ich bevorzuge es, ein benutzerdefiniertes Prädikat dafür zu verwenden:quelle
Es kommt darauf an, wie groß der Datensatz ist und welche Leistungsanforderungen Sie haben.
Wenn es nichts Gigantisches ist, verwenden Sie die am besten lesbare Form, die für mich eine ist, weil sie kürzer und lesbarer ist als eine Gleichung.
quelle
Über die Count () -Methode: Wenn die IEnumarable eine ICollection ist , können wir nicht über alle Elemente iterieren, da wir das Count- Feld der ICollection abrufen können. Wenn die IEnumerable keine ICollection ist , müssen wir mit einer Weile mit über alle Elemente iterieren Schauen Sie sich in einem MoveNext den .NET Framework-Code an:
Referenz: Referenzquelle aufzählbar
quelle
Sie können einen einfachen Test durchführen, um dies herauszufinden:
Überprüfen Sie die Werte von testCount und testAny.
quelle
Count
durch die Methode Count () vs .Any () keine Eigenschaft ersetzt werden. Sie benötigen Zeit für Iterationen.Wenn Sie das Entity Framework verwenden und eine große Tabelle mit vielen Datensätzen haben, ist Any () viel schneller. Ich erinnere mich, dass ich einmal überprüfen wollte, ob eine Tabelle leer war und Millionen von Zeilen hatte. Es dauerte 20 bis 30 Sekunden, bis Count ()> 0 abgeschlossen war. Es war sofort mit Any () .
Any () kann eine Leistungsverbesserung sein, da die Auflistung möglicherweise nicht iteriert werden muss, um die Anzahl der Dinge zu ermitteln. Es muss nur einen von ihnen treffen. Oder zum Beispiel für LINQ-to-Entities lautet das generierte SQL IF EXISTS (...) und nicht SELECT COUNT ... oder sogar SELECT * ....
quelle