Me he encontrado con artículos que dicen que SELECT COUNT(*) FROM TABLE_NAME
será lento cuando la tabla tenga muchas filas y muchas columnas.
Tengo una tabla que puede contener incluso miles de millones de filas [tiene aproximadamente 15 columnas]. ¿Hay una mejor manera de obtener el recuento EXACTO del número de filas de una tabla?
Por favor considere lo siguiente antes de su respuesta:
Estoy buscando una solución independiente del proveedor de la base de datos. Está bien si cubre MySQL , Oracle , MS SQL Server . Pero si realmente no hay una solución independiente del proveedor de la base de datos, me conformaré con diferentes soluciones para diferentes proveedores de bases de datos.
No puedo usar ninguna otra herramienta externa para hacer esto. Estoy buscando principalmente una solución basada en SQL.
No puedo normalizar más el diseño de mi base de datos. Ya está en 3NF y, además, ya se ha escrito mucho código a su alrededor.
Respuestas:
Respuesta simple:
COUNT(*)
Notas:
COUNT (1) = COUNT (*) = COUNT (PrimaryKey) por si acaso
Editar:
Ejemplo de SQL Server (1.4 billones de filas, 12 columnas)
1 carrera, 5:46 minutos, cuenta = 1,401,659,700
2 carreras, ambas de menos de 1 segundo, cuenta = 1,401,659,670
El segundo tiene menos filas = incorrecto. Sería igual o más dependiendo de las escrituras (las eliminaciones se realizan fuera de horario aquí)
fuente
COUNT(*) = COUNT(key)
. Esto está mal. Si no hayNOT NULL
restricción, entonces no pueden ser iguales (en los resultados y en el plan de ejecución).index_id < 2
?La forma más rápida con diferencia en MySQL es:
Obtendrá instantáneamente todas sus tablas con el recuento de filas (que es el total) junto con mucha información adicional si lo desea.
fuente
Eso depende de la base de datos. Algunos acelera el recuento, por ejemplo, al realizar un seguimiento de si las filas están activas o muertas en el índice, lo que permite que un escaneo de índice solo extraiga el número de filas. Otros no lo hacen, y en consecuencia requieren visitar toda la mesa y contar las filas en vivo una por una. Cualquiera será lento para una mesa enorme.
Tenga en cuenta que generalmente puede extraer una buena estimación mediante el uso de herramientas de optimización de consultas, estadísticas de tabla, etc. En el caso de PostgreSQL, por ejemplo, podría analizar la salida
explain count(*) from yourtable
y obtener una estimación razonablemente buena del número de filas. Lo que me lleva a tu segunda pregunta.¿Seriamente? :-) ¿Realmente quieres decir el recuento exacto de una tabla con miles de millones de filas? ¿Estas realmente seguro? :-)
Si realmente lo hace, podría mantener un rastro del total utilizando disparadores, pero tenga en cuenta la concurrencia y los puntos muertos si lo hace.
fuente
Para responder a su pregunta simplemente, no .
Si necesita una forma independiente de DBMS de hacer esto, la forma más rápida siempre será:
Algunos proveedores de DBMS pueden tener formas más rápidas que funcionarán solo para sus sistemas. Algunas de estas opciones ya están publicadas en otras respuestas.
COUNT(*)
debería ser optimizado por el DBMS (al menos cualquier DB digno de PROD) de todos modos, así que no intentes evitar sus optimizaciones.Como nota al margen:
estoy seguro de que muchas de sus otras consultas también tardan mucho tiempo en completarse debido al tamaño de su tabla. Cualquier problema de rendimiento probablemente debería abordarse pensando en el diseño de su esquema teniendo en cuenta la velocidad. Me doy cuenta de que dijiste que no es una opción cambiar, pero podría resultar que las consultas de más de 10 minutos tampoco lo sean. 3rd NF no siempre es el mejor enfoque cuando necesita velocidad, y a veces los datos se pueden dividir en varias tablas si los registros no tienen que almacenarse juntos. Algo sobre lo que pensar...
fuente
Recibí este script de otra pregunta / respuesta de StackOverflow:
Mi tabla tiene 500 millones de registros y lo anterior devuelve en menos de 1 ms. Mientras tanto,
¡Toma 39 minutos completos, 52 segundos!
Producen exactamente el mismo número de filas (en mi caso, exactamente 519326012).
No sé si ese sería siempre el caso.
fuente
Puede probar esto sp_spaceused (Transact-SQL)
fuente
Si la edición de SQL Server es 2005/2008, puede usar DMV para calcular el recuento de filas en una tabla:
Para el motor de base de datos SQL Server 2000, sysindexes funcionará, pero se recomienda encarecidamente evitar usarlo en futuras ediciones de SQL Server, ya que puede eliminarse en un futuro próximo.
Código de muestra tomado de: Cómo obtener recuentos de filas de tabla de forma rápida e indolora
fuente
yo suelo
fuente
No soy tan experto como otros que respondieron, pero estaba teniendo un problema con un procedimiento que estaba usando para seleccionar una fila aleatoria de una tabla (no demasiado relevante) pero necesitaba saber el número de filas en mi tabla de referencia para calcular el índice aleatorio. Utilizando el trabajo tradicional Count (*) o Count (1), pero ocasionalmente obtenía hasta 2 segundos para que se ejecutara mi consulta. Entonces, en cambio (para mi tabla llamada 'tbl_HighOrder') estoy usando:
Funciona muy bien y los tiempos de consulta en Management Studio son cero.
fuente
Bueno, tarde por 5 años e inseguro si ayuda:
Estaba tratando de contar el no. de filas en una tabla de SQL Server usando MS SQL Server Management Studio y encontré algún error de desbordamiento, luego usé lo siguiente:
seleccione count_big (1) FROM [dbname]. [dbo]. [FactSampleValue];
El resultado :
24296650578 filas
fuente
He encontrado este buen artículo de SQL Server-HOW-TO: recuperar rápidamente precisa recuento de filas para la tabla de
martijnh1
lo que le da un buen resumen para cada escenario.Necesito que esto se expanda donde necesito proporcionar un recuento basado en una condición específica y cuando calcule esta parte, actualizaré esta respuesta aún más.
Mientras tanto, aquí están los detalles del artículo:
Método 1:
Consulta:
Comentarios:
Realiza un escaneo completo de la tabla. Reduzca la velocidad en mesas grandes.
Método 2:
Consulta:
Comentarios:
Manera rápida de recuperar el recuento de filas. Depende de las estadísticas y es inexacto.
Ejecute DBCC UPDATEUSAGE (Base de datos) CON COUNT_ROWS, que puede llevar un tiempo considerable para tablas grandes.
Método 3:
Consulta:
Comentarios:
La forma en que el estudio de administración de SQL cuenta las filas (observe las propiedades de la tabla, el almacenamiento, el recuento de filas). Muy rápido, pero sigue siendo un número aproximado de filas.
Método 4:
Consulta:
Comentarios:
Operación rápida (aunque no tan rápida como el método 2) e igualmente importante, confiable.
fuente
No creo que haya una solución general siempre más rápida: algunos RDBMS / versiones tienen una optimización específica para
SELECT COUNT(*)
usar opciones más rápidas, mientras que otros simplemente escanean la tabla. Tendría que ir a los sitios de documentación / soporte para el segundo conjunto, que probablemente necesitará alguna consulta más específica para ser escrita, generalmente una que llegue a un índice de alguna manera.EDITAR:
Aquí hay una idea que podría funcionar, dependiendo de su esquema y distribución de datos: ¿tiene una columna indexada que haga referencia a un valor creciente, una identificación numérica creciente, por ejemplo, o incluso una marca de tiempo o fecha? Luego, suponiendo que no se eliminen, debería ser posible almacenar el recuento hasta un valor reciente (la fecha de ayer, el valor de ID más alto en algún punto de muestra reciente) y agregar el recuento más allá de eso, lo que debería resolverse muy rápidamente en el índice . Muy dependiente de valores e índices, por supuesto, pero aplicable a casi cualquier versión de cualquier DBMS.
fuente
SELECT COUNT(*)
. Incluso MySQL aparentemente lo hace ....Llego tarde a esta pregunta, pero esto es lo que puede hacer con MySQL (ya que uso MySQL). Estoy compartiendo mis observaciones aquí:
Recuento de filas de resultados : 508534
Salida de la consola: Filas afectadas: 0 Filas encontradas: 1 Advertencias: 0 Duración para 1 consulta: 0,125 segundos.
Toma un tiempo para una tabla con un gran número de filas, pero el recuento de filas es muy exacto.
Resultado
Recuento de filas: 511235
Salida de la consola: Filas afectadas: 0 Filas encontradas: 1 Advertencias: 0 Duración para 1 consulta: 0.250 segundos Resumen: El recuento de filas no es exacto.
Resultado
Recuento de filas: 507806
Salida de la consola: Filas afectadas: 0 Filas encontradas: 48 Advertencias: 0 Duración para 1 consulta: 1.701 seg.
El recuento de filas no es exacto.
No soy un experto en MySQL o en bases de datos, pero he descubierto que para tablas muy grandes, puede usar la opción 2 o 3 y obtener una 'idea justa' de cuántas filas están presentes.
Necesitaba obtener estos recuentos de filas para mostrar algunas estadísticas en la interfaz de usuario. Con las consultas anteriores, sabía que las filas totales eran más de 500,000, por lo que se me ocurrió mostrar estadísticas como "Más de 500,000 filas" sin mostrar el número exacto de filas.
Tal vez no he respondido realmente a la pregunta del OP, pero estoy compartiendo lo que hice en una situación en la que se necesitaban esas estadísticas. En mi caso, mostrar las filas aproximadas era aceptable y, por lo tanto, lo anterior funcionó para mí.
fuente
No es exactamente una solución independiente de DBMS, pero al menos su código de cliente no verá la diferencia ...
Cree otra tabla T con solo una fila y un campo entero N 1 , y cree INSERT TRIGGER que simplemente ejecute:
También cree un DELETE TRIGGER que ejecute:
Un DBMS que valga la pena garantizará la atomicidad de las operaciones por encima de 2 , y N contendrá el recuento exacto de filas en todo momento, que luego es súper rápido de obtener simplemente:
Si bien los disparadores son específicos de DBMS, la selección de T no lo es y su código de cliente no tendrá que cambiar para cada DBMS compatible.
Sin embargo, esto puede tener algunos problemas de escalabilidad si la tabla es INSERT o DELETE, especialmente si no se COMPROMETE inmediatamente después de INSERT / DELETE.
1 Estos nombres son solo marcadores de posición: use algo más significativo en la producción.
2 Ie N no se puede cambiar mediante una transacción concurrente entre leer y escribir en N, siempre que tanto la lectura como la escritura se realicen en una sola instrucción SQL.
fuente
Una respuesta literalmente loca, pero si tienes algún tipo de sistema de replicación configurado (para un sistema con mil millones de filas, espero que lo hagas), puedes usar un estimador aproximado (como
MAX(pk)
), divide ese valor por el número de esclavos tienes, ejecuta varias consultas en paralelo.En su mayor parte, dividiría las consultas entre esclavos en función de la mejor clave (o la clave principal, supongo), de esa manera (vamos a utilizar 250000000 como nuestras filas / esclavos):
Pero solo necesita SQL. Que busto. Ok, digamos que eres un sadomasoquista. En el maestro (o esclavo más cercano) lo más probable es que necesite crear una tabla para esto:
Entonces, en lugar de solo tener las selecciones ejecutándose en sus esclavos, tendría que hacer una inserción, similar a esto:
Puede tener problemas con los esclavos que escriben en una tabla en master. Es posible que necesite obtener aún más sadis, quiero decir, creativo:
Al final, debe tener un esclavo que exista en último lugar en la ruta recorrida por el gráfico de replicación, en relación con el primer esclavo. Ese esclavo ahora debería tener todos los demás valores de contador, y debería tener sus propios valores. Pero para cuando haya terminado, probablemente haya filas agregadas, por lo que tendría que insertar otra que compense el max pk registrado en su counter_table y el max pk actual.
En ese punto, tendrías que hacer una función de agregado para determinar cuáles son las filas totales, pero eso es más fácil ya que lo estarías ejecutando en la mayoría de las filas de "número de esclavos que tienes y cambias".
Si se encuentra en una situación en la que tiene tablas separadas en los esclavos, puede
UNION
obtener todas las filas que necesita.O ya sabe, sea un poco menos loco y migre sus datos a un sistema de procesamiento distribuido, o tal vez use una solución de Data Warehousing (que también le proporcionará una increíble capacidad de procesamiento de datos en el futuro).
Tenga en cuenta que esto depende de qué tan bien esté configurada su replicación. Dado que el cuello de botella principal probablemente sea el almacenamiento persistente, si tiene un almacenamiento inadecuado o almacenes de datos mal segregados con un fuerte ruido vecino, esto probablemente lo hará más lento que solo esperar un solo
SELECT COUNT(*) ...
Pero si tiene una buena replicación, sus ganancias de velocidad deben estar directamente relacionadas con el número o los esclavos. De hecho, si lleva solo 10 minutos ejecutar la consulta de conteo y tiene 8 esclavos, reduciría su tiempo a menos de un par de minutos. Tal vez una hora para resolver los detalles de esta solución.
Por supuesto, nunca obtendría una respuesta increíblemente precisa, ya que esta solución distribuida introduce un poco de tiempo en el que las filas se pueden eliminar e insertar, pero puede intentar obtener un bloqueo distribuido de filas en la misma instancia y obtener un recuento preciso de las filas en la tabla para un momento particular en el tiempo.
En realidad, esto parece imposible, ya que básicamente está atrapado con una solución solo de SQL, y no creo que haya proporcionado un mecanismo para ejecutar una consulta fragmentada y bloqueada a través de múltiples esclavos, instantáneamente. Tal vez si tuviera el control del archivo de registro de replicación ... lo que significa que literalmente estaría haciendo girar esclavos para este propósito, lo que sin duda es más lento que simplemente ejecutar la consulta de conteo en una sola máquina de todos modos.
Así que ahí están mis dos centavos de 2013.
fuente
Si el desencadenador de inserción es demasiado costoso de usar, pero podría permitirse un desencadenador de eliminación , y hay un incremento automático
id
, luego de contar toda la tabla una vez y recordar el conteo comolast-count
ylast-counted-id
,entonces cada día solo necesita contar para
id
>last-counted-id
, agregar esolast-count
y almacenar el nuevolast-counted-id
.El activador de eliminación disminuiría el último recuento, si la identificación del registro eliminado <= último-contado-id.
fuente
Si tiene una estructura de tabla típica con una columna de clave principal de incremento automático en la que las filas nunca se eliminan, la siguiente será la forma más rápida de determinar el recuento de registros y debería funcionar de manera similar en la mayoría de las bases de datos compatibles con ANSI:
Trabajo con tablas MS SQL que contienen miles de millones de filas que requieren tiempos de respuesta inferiores a un segundo para los datos, incluidos los recuentos de registros. Un RECUENTO SELECCIONADO similar (*) tomaría minutos en procesarse en comparación.
fuente
INSERT
se revierte una transacción? Ese valor de clave principal estaría ausente, por lo que el recuento de registros real sería uno menos que el valor máximo.count(*)
, si un proveedor de base de datos no se ha optimizado lo suficientecount(*)
: cada día realice un seguimiento del último índice automático y su recuento correspondiente, luego solicite un recuento de registros más allá de eso. También puede manejardelete
s si agrega un disparador al eliminar que disminuye el total anterior , si se eliminó el ID de registro <= ese último índice automático.Para el servidor SQL intente esto
fuente
seleccione filas de sysindexes donde id = Object_ID ('TableName') e indid <2
fuente
Pon un índice en alguna columna. Eso debería permitir que el optimizador realice una exploración completa de los bloques de índice, en lugar de una exploración completa de la tabla. Eso reducirá sus costos de IO mucho más. Mira el plan de ejecución antes y después. Luego mida el tiempo del reloj de pared en ambos sentidos.
fuente
Si está utilizando Oracle, ¿qué tal esto (suponiendo que las estadísticas de la tabla estén actualizadas):
last_analyzed mostrará la hora en que se recopilaron las estadísticas por última vez.
fuente
Con PostgreSQL:
fuente
En SQL Server 2016, solo puedo verificar las propiedades de la tabla y luego seleccionar la pestaña 'Almacenamiento'; esto me da el recuento de filas, el espacio en disco utilizado por la tabla, el espacio de índice utilizado, etc.
fuente
database vendor independent solution
. Además, esto requiere una GUI y no se puede automatizar. Además, no es más rápido como COUNT (*)Tal vez un poco tarde, pero esto podría ayudar a otros para MSSQL
fuente