en el System.Linq
espacio de nombres, ahora podemos extender nuestros IEnumerables para tener Any () y Count () métodos de extensión .
Recientemente me dijeron que si quiero verificar que una colección contenga 1 o más elementos dentro de ella, debería usar el .Any()
método de extensión en lugar del método de .Count() > 0
extensión porque el .Count()
método de extensión tiene que recorrer en iteración todos los elementos.
En segundo lugar, algunas colecciones tienen una propiedad (no un método de extensión) que es Count
o Length
. ¿Sería mejor usarlos, en lugar de .Any()
o .Count()
?
si / nae?
.net
linq
performance
.net-3.5
extension-methods
Pure.Krome
fuente
fuente
Respuestas:
Si usted está comenzando con algo que tiene una
.Length
o.Count
(como por ejemploICollection<T>
,IList<T>
,List<T>
, etc.) - entonces esto va a ser la opción más rápida, ya que no tiene que pasar por laGetEnumerator()
/MoveNext()
/Dispose()
secuencia requerida porAny()
comprobar para un no-vacíoIEnumerable<T>
secuencia .Por tan sólo
IEnumerable<T>
, entoncesAny()
será generalmente más rápido, ya que sólo tiene que mirar a una iteración. Sin embargo, tenga en cuenta que la implementación de LINQ-to-ObjectsCount()
compruebaICollection<T>
(utilizando.Count
como una optimización), por lo que si su fuente de datos subyacente es directamente una lista / colección, no habrá una gran diferencia. No me preguntes por qué no usa el no genéricoICollection
...Por supuesto, si ha utilizado LINQ para filtrarlo, etc. (
Where
etc.), tendrá una secuencia basada en bloques iteradores, por lo que estaICollection<T>
optimización es inútil.En general con
IEnumerable<T>
: seguir conAny()
;-pfuente
(somecollection.Count > 0)
? ¿Fue difícil de entender todo nuestro código antes de la introducción del método .Any () de LINQ?someCollection.Count > 0
es tan clarosomeCollection.Any()
y tiene el beneficio adicional de un mayor rendimiento y de no requerir LINQ. Por supuesto, este es un caso muy simple y otras construcciones que usan operadores LINQ transmitirán la intención de los desarrolladores mucho más clara que la opción equivalente que no es LINQ.Nota: escribí esta respuesta cuando Entity Framework 4 era real. El objetivo de esta respuesta era no entrar en pruebas triviales
.Any()
versus de.Count()
rendimiento. El punto era señalar que EF está lejos de ser perfecto. Las versiones más nuevas son mejores ... pero si tiene una parte del código que es lenta y usa EF, pruebe con TSQL directo y compare el rendimiento en lugar de confiar en suposiciones (eso.Any()
es SIEMPRE más rápido que.Count() > 0
).Si bien estoy de acuerdo con la mayoría de las respuestas y comentarios votados, especialmente sobre el punto, las
Any
señales del desarrollador son mejoresCount() > 0
, he tenido una situación en la que Count es más rápido por orden de magnitud en SQL Server (EntityFramework 4).Aquí hay una consulta con
Any
esa excepción de tiempo de espera (en ~ 200,000 registros):Count
versión ejecutada en cuestión de milisegundos:Necesito encontrar una manera de ver qué SQL exacto producen ambos LINQ, pero es obvio que hay una gran diferencia de rendimiento entre
Count
yAny
en algunos casos, y desafortunadamente parece que no puede quedarseAny
en todos los casos.EDITAR: Aquí se generan los SQL. Bellezas como puedes ver;)
ANY
:COUNT
:Parece que puro Where with EXISTS funciona mucho peor que calcular Count y luego hacer Where with Count == 0.
Avíseme si ustedes ven algún error en mis hallazgos. Lo que se puede sacar de todo esto, independientemente de la discusión Any vs Count es que cualquier LINQ más complejo está mucho mejor cuando se reescribe como Procedimiento almacenado;).
fuente
Como este es un tema bastante popular y las respuestas difieren, tuve que volver a analizar el problema.
Prueba de env: EF 6.1.3, SQL Server, 300k registros
Modelo de mesa :
Código de prueba:
Resultados:
Cualquiera () ~ 3 ms
Count () ~ 230ms para la primera consulta, ~ 400ms para la segunda
Observaciones:
Para mi caso, EF no generó SQL como @Ben mencionado en su publicación.
fuente
Count() > 0
. : DEDITAR: se corrigió en EF versión 6.1.1. y esta respuesta ya no es real
Para SQL Server y EF4-6, Count () se desempeña aproximadamente dos veces más rápido que Any ().
Cuando ejecutas Table.Any (), generará algo como ( alerta: no hagas daño al cerebro tratando de entenderlo )
eso requiere 2 escaneos de filas con su condición.
No me gusta escribir
Count() > 0
porque oculta mi intención. Prefiero usar un predicado personalizado para esto:fuente
Depende, ¿qué tan grande es el conjunto de datos y cuáles son sus requisitos de rendimiento?
Si no es nada gigantesco, use la forma más legible, que para mí es cualquiera, porque es más corta y legible en lugar de una ecuación.
fuente
Sobre el método Count () , si IEnumarable es una ICollection , entonces no podemos iterar en todos los elementos porque podemos recuperar el campo Count de ICollection , si IEnumerable no es una ICollection , debemos iterar en todos los elementos usando un tiempo con un MoveNext , echar un vistazo al código de .NET Framework:
Referencia: Fuente de referencia Enumerable
fuente
Puedes hacer una prueba simple para resolver esto:
Verifique los valores de testCount y testAny.
fuente
Count
reemplazar por el método Count () vs .Any () no es una propiedad. Necesita tiempo de iteraciones.Si está utilizando Entity Framework y tiene una tabla enorme con muchos registros, Any () será mucho más rápido. Recuerdo una vez que quería comprobar si una mesa estaba vacía y tenía millones de filas. Tomó 20-30 segundos para que Count ()> 0 se completara. Fue instantáneo con Any () .
Any () puede ser una mejora del rendimiento porque es posible que no tenga que iterar la colección para obtener la cantidad de cosas. Solo tiene que golpear a uno de ellos. O, por ejemplo, para LINQ-to-Entities, el SQL generado será IF EXISTS (...) en lugar de SELECT COUNT ... o incluso SELECT * ....
fuente