2009-02-16 25 views
10

estoy usando interfaces de IQueryable<T> lo largo de mi solicitud y aplazar la ejecución de SQL en la base de datos hasta que métodos como .ToList()count VS seleccionar en LINQ - ¿cuál es más rápido?

que tendrá que encontrar el Conde de ciertas listas veces -without- necesidad de utilizar los datos en el ser lista contado Sé por experiencia SQL que un SQL COUNT() es mucho menos trabajo para el DB que la sentencia SELECT equivalente que devuelve todas las filas.

Así que mi pregunta es: ¿será menos trabajo en la base de datos para devolver el recuento de Count() método de la IQueryable<T> 's que la reproducción de la IQueryable<T> a una lista e invocando el método de la lista Count()?

Sospecho que, dado que ToList() disparará el SELECT sql y luego en una consulta separada cuente las filas. Espero que el Count() en el IQueryable<T> simplemente represente el sql para una consulta sql COUNT() en su lugar. Pero no estoy seguro. ¿Tú sabes?

Respuesta

20

Llamar a ToList() devolverá un List<T> genuino con todos los datos, lo que significa recuperar todos los datos. No está bien.

Llamar a Count() debería hacer que el SQL haga la cuenta en el lado de la base de datos. Mucho mejor.

La forma más sencilla de comprobar esto, sin embargo, es habilitar el registro en su contexto de datos (o cualquiera que sea el equivalente para su proveedor en particular) y ver qué consultas se están enviando en realidad.

+0

thanx Jon. Puedo verificar que el método Count() de IQueryable hace gen el SQL COUNT() correcto en lugar de la propiedad Count de la lista que debe tener activado el SELECT. Aquí también hay un TextWriter Kool para aquellos que quieren ver el registro: http: //www.u2u.info/Blogs/Kris/Lists/Posts/Post.aspx? ID = 11 –

+1

¡El COUNT del servidor Sql aún será lento ya que causa un escaneo de tabla! – Slaggg

+1

@Slaggg, si tiene un índice, solo realizará un escaneo de índice en el índice más pequeño que tenga. Si no tiene índices, aún reducirá la carga de red en el servidor de la base de datos (en comparación con la devolución de todas las filas). –

-1

No estoy seguro si es una regla difícil pero el método linq que agrega a un Iqueryable se agregará al árbol de expresiones linq, a menos que sean uno de los métodos que realmente hacen que el árbol sea evaluado (como ToList e Individual, etc.). En el caso de LinqToSql, sabrá si no puede convertir algo en la declaración de SQL porque obtendrá una excepción de tiempo de ejecución que indica que el método no es compatible.

por ejemplo

var something = dbContext.SomeTable 
    .Select(c => c.col1 == "foo") 
    .Distinct() 
    .ToList() 
    .Count() 

En lo anterior, Select() y Distinct() se incluyen en la consulta SQL pasa al servidor, ya que se añaden a una IQueryable. Count() solo está actuando en la lista que devolvió la consulta sql. Entonces no quiere hacerlo de esa manera :-)

En su caso, Count() definitivamente será más rápido que Select() porque el enunciado sql resultante incorporará el conteo de modo que el servidor solo tiene que devolver un solo número en lugar de una lista de filas.

-1

Si está utilizando SQL Server, Count() sigue siendo muy caro porque causa un escaneo de tabla (o escaneo de índice, vea comentarios en la respuesta principal). Y, de forma predeterminada, Linq no utiliza el nivel de aislamiento sin lectura, lo que empeora las cosas debido al bloqueo.

Si puede vivir con el resultado siendo un resultado sucio y una aproximación del número total de filas, el siguiente código será considerablemente más rápido que usar Count(). En mi experiencia, el valor devuelto por este código rara vez es diferente al recuento real de filas.

/// <summary>A very fast method for counting rows in a table.</summary> 
public static long FastRowCount(DataContext context, string tableName) 
{ 
    const string template = "SELECT rowcnt FROM sys.sysindexes WHERE id = OBJECT_ID('{0}') AND indid < 2"; 
    string query = string.Format(template, tableName); 
    return context.ExecuteQuery<long>(query).Single(); 
} 
+0

Es una suposición razonable que todo lo que alguien está contando en un entorno de producción será indexado. –

Cuestiones relacionadas