viewcomponent pages net mvc aspx asp asp.net sql-server-2005 performance premature-optimization

asp.net - pages - render partial asp net core



¿Es la cuenta(*) realmente costosa? (7)

Tengo una página donde tengo 4 pestañas que muestran 4 informes diferentes basados ​​en diferentes tablas.

Obtengo el recuento de filas de cada tabla utilizando un select count(*) from <table> y visualizo el número de filas disponibles en cada tabla en las pestañas. Como resultado, cada devolución de página hace que se ejecuten 5 conteos count(*) consultas (4 para obtener conteos y 1 para paginación) y 1 consulta para obtener el contenido del informe.

Ahora mi pregunta es: ¿son las consultas de la count(*) realmente caras? ¿Debo mantener las cuentas de la fila (al menos las que se muestran en la pestaña) en el estado de vista de la página en lugar de consultar varias veces?

¿Qué tan caras son las consultas COUNT (*)?


COUNT (*) puede ser particularmente costoso, ya que puede resultar en la carga (y paginación) de una tabla completa, donde es posible que solo necesite un recuento en una clave principal (en algunas implementaciones está optimizado).

Por lo que parece, está provocando una operación de carga de tablas cada vez, lo cual es lento, pero a menos que se ejecute notablemente lento, o cause algún tipo de problema, no optimice: la optimización prematura e innecesaria puede causar una gran cantidad de ¡problema!

Un recuento en una clave primaria indexada será mucho más rápido, pero con los costos de tener un índice, esto no puede proporcionar ningún beneficio.


Como han dicho otros, COUNT(*) siempre cuenta físicamente las filas, así que si puedes hacer eso una vez y almacenar los resultados, eso es ciertamente preferible.

Si realiza una evaluación comparativa y determina que el costo es insignificante, no tiene (actualmente) un problema.

Si resulta demasiado costoso para su escenario, puede hacer que su paginación sea "borrosa" como en " Mostrando 1 a 500 de aproximadamente 30,000 " usando

SELECT rows FROM sysindexes WHERE id = OBJECT_ID(''sometable'') AND indid < 2

que devolverá una aproximación del número de filas (es aproximado porque no se actualiza hasta un PUNTO DE CONTROL).


En general, el costo de COUNT(*) es proporcional al número de registros que satisfacen las condiciones de consulta más el tiempo requerido para preparar estos registros (que depende de la complejidad de la consulta subyacente).

En los casos simples en los que se trata de una sola tabla, a menudo hay optimizaciones específicas para hacer que esta operación sea barata. Por ejemplo, hacer COUNT(*) sin las condiciones de WHERE de una sola tabla MyISAM en MySQL , esto es instantáneo ya que se almacena en metadatos.

Por ejemplo, consideremos dos consultas:

SELECT COUNT(*) FROM largeTableA a

Dado que cada registro satisface la consulta, el costo de COUNT(*) es proporcional al número de registros en la tabla (es decir, proporcional a lo que devuelve) (Suponiendo que sea necesario visitar las filas y no hay una optimización específica para manejar eso)

SELECT COUNT(*) FROM largeTableA a JOIN largeTableB b ON a.id = b.id

En este caso, el motor probablemente usará HASH JOIN y el plan de ejecución será algo como esto:

  1. Construye una tabla hash en la más pequeña de las tablas
  2. Escanee la tabla más grande, buscando cada registro en una tabla hash
  3. Cuente los partidos a medida que avanzan.

En este caso, la sobrecarga de COUNT(*) (paso 3) será despreciable y el tiempo de consulta se definirá completamente en los pasos 1 y 2, que es la construcción de la tabla hash y su búsqueda. Para tal consulta, el tiempo será O(a + b) : en realidad no depende del número de coincidencias.

Sin embargo, si hay índices tanto en a.id como en b.id , se puede elegir MERGE JOIN y el tiempo COUNT(*) será proporcional al número de coincidencias nuevamente, ya que se realizará una búsqueda de índice después de cada coincidencia.


Esto depende de lo que esté haciendo con los datos en esta tabla. Si están cambiando muy a menudo y los necesita todos cada vez, tal vez podría hacer un desencadenante que llenará otra tabla que solo consiste en conteos de esta tabla. Si necesita mostrar estos datos por separado, tal vez podría ejecutar "select count (*) ..." para solo una tabla en particular. Esto me vino a la mente al instante, pero hay otras formas de acelerar esto, estoy seguro. Datos de caché, tal vez? :)


Si la página se vuelve lenta, una cosa que puede observar es minimizar el número de viajes de ida y vuelta a la base de datos, si es posible. Incluso si sus consultas COUNT(*) son O (1), si está haciendo lo suficiente, eso podría ralentizar las cosas.

En lugar de configurar y ejecutar 5 consultas separadas una por una, ejecute las SELECT en un solo lote y procese los 5 resultados a la vez.

Es decir, si está utilizando ADO.NET, haga algo como esto (comprobación de errores omitida por brevedad; no en bucle / no dinámica por claridad):

string sql = "SELECT COUNT(*) FROM Table1; SELECT COUNT(*) FROM Table2;" SqlCommand cmd = new SqlCommand(sql, connection); SqlDataReader dr = cmd.ExecuteReader(); // Defaults to first result set dr.Read(); int table1Count = (int)dr[0]; // Move to second result set dr.NextResult(); dr.Read(); int table2Count = (int)dr[0];

Si está utilizando un ORM de algún tipo, como NHibernate, debería haber una manera de habilitar el procesamiento de lotes automático de consultas.


Toda la E / S es costosa y si puede realizar la tarea sin ella, debería hacerlo. Pero si es necesario, no me preocuparía por eso.

Usted menciona el almacenamiento de los conteos en estado de visualización, sin duda una opción, siempre que el comportamiento del código sea aceptable cuando ese conteo sea incorrecto porque los registros subyacentes hayan desaparecido o se hayan agregado.


Debe adjuntar el Analizador de SQL o un generador de perfiles de nivel de aplicación como L2SProf y ver los costos de consulta reales en su contexto antes:

  • adivinar cuál es el problema y tratar de determinar los posibles beneficios de una solución potencial

  • Permitir que otros adivinen para usted en las redes interconectadas: hay mucha información errónea sin citas, incluido en este hilo (pero no en esta publicación: P)

Cuando haya hecho eso, quedará claro cuál es el mejor enfoque, es decir, si SELECT COUNT está dominando las cosas o no, etc.

Y una vez hecho esto, también sabrá si cualquier cambio que elija ha tenido un impacto positivo o negativo.