¿La forma más rápida de contar el número exacto de filas en una tabla muy grande?

234

Me he encontrado con artículos que dicen que SELECT COUNT(*) FROM TABLE_NAMEserá 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.

Swaranga Sarma
fuente
44
Y la curiosidad por qué se necesita la cantidad instante exacto de filas cuando se tiene miles de ellos ...
zerkms
2
¿No esperaríamos todos que esta construcción en particular haya sido optimizada por nuestro proveedor de bases de datos?
KevinDTimm
55
@Swaranga, ¿puede aclarar un poco más sobre cuál es el propósito del mantenimiento de esta base de datos que debe conocer el número exacto de filas en la tabla? No me lo puedo imaginar. Y como dice Kevin, si hubiera una forma más rápida que COUNT (*), entonces el proveedor de DBMS (seguramente) volvería a implementar COUNT (*) para usarlo ...
Tony Andrews
3
Seguramente, si la tabla se escribe con frecuencia, entonces su recuento exacto solo será exacto para un punto en el tiempo en particular, y puede que ni siquiera sea exacto si otros procesos están escribiendo en la tabla, a menos que coloque un bloqueo de tabla en la consulta.
Steve Ford
2
¿Podría usar disparadores de inserción y eliminación para mantener un recuento continuo?
paparazzo

Respuestas:

246

Respuesta simple:

  • Solución independiente del proveedor de la base de datos = use el estándar = COUNT(*)
  • Hay soluciones aproximadas de SQL Server pero no use COUNT (*) = fuera de alcance

Notas:

COUNT (1) = COUNT (*) = COUNT (PrimaryKey) por si acaso

Editar:

Ejemplo de SQL Server (1.4 billones de filas, 12 columnas)

SELECT COUNT(*) FROM MyBigtable WITH (NOLOCK)
-- NOLOCK here is for me only to let me test for this answer: no more, no less

1 carrera, 5:46 minutos, cuenta = 1,401,659,700

--Note, sp_spaceused uses this DMV
SELECT
   Total_Rows= SUM(st.row_count)
FROM
   sys.dm_db_partition_stats st
WHERE
    object_name(object_id) = 'MyBigtable' AND (index_id < 2)

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í)

gbn
fuente
99
No, COUNT(*) = COUNT(key). Esto está mal. Si no hay NOT NULLrestricción, entonces no pueden ser iguales (en los resultados y en el plan de ejecución).
zerkms
14
@zerkmsby: para COUNT (clave) quise decir COUNT (clave principal) que no debe ser anulable. Aclararé
gbn
8
with (NOLOCK) no es algo que le permita ejecutarse en producción, y puede conducir a un recuento inexacto. Cuando use esa sugerencia, asegúrese de que evita bloqueos, pero los efectos secundarios en una caja de producción son que puede contar filas dos veces en algunas situaciones u omitir filas en otras situaciones. Es mejor usar NOLOCK en una tabla en la que no se está escribiendo porque permite "lecturas sucias". No aconseje a las personas que usen esa pista a menos que comprendan completamente las consecuencias
Davos
44
@mishrsud La única consulta precisa es SELECT COUNT (*), pero es lenta. Puede ser exacto y lento, o áspero y rápido. Lo que haga dependerá de lo que sea más importante para el propósito para el que necesita el conteo. NO BLOQUEO puede incluir o excluir filas que son transacciones intermedias o páginas móviles por cualquier motivo.
Davos
55
@gbn muy buena solución, ¿puedes decir de qué sirve index_id < 2?
comprometerse el
29

La forma más rápida con diferencia en MySQL es:

SHOW TABLE STATUS;

Obtendrá instantáneamente todas sus tablas con el recuento de filas (que es el total) junto con mucha información adicional si lo desea.

salbahra
fuente
1
Forma inteligente ... con esto puede obtener el recuento de filas de varias tablas en 1 consulta.
Deval Khandelwal
¿corriste en db teniendo tablas con ~ billones de entradas como @gbn y notaste la hora?
KNU
¿Qué valor es el recuento total de filas para todas las tablas en la base de datos? Y estos son aproximados: ¿qué sucede si desea valores exactos de recuento de filas?
Kreeverp
2
esto no funciona en absoluto, en INNODB, por ejemplo, el motor de almacenamiento lee algunas filas y extrapola para adivinar el número de filas
Martijn Scheffer
10

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.

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 yourtabley obtener una estimación razonablemente buena del número de filas. Lo que me lleva a tu segunda pregunta.

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?

¿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.

Denis de Bernardy
fuente
Sí Denis, se requiere el conteo exacto. :(
Swaranga Sarma
55
Es una suerte que los gerentes de Google sean más razonables que su jefe ... Imagine lo lento que sería si devolviera el número exacto de resultados de búsqueda para cada una de sus consultas en lugar de apegarse a un número estimado.
Denis de Bernardy
Al menos empatizas conmigo. ¿Qué tal una única solución de Oracle? Eso reducirá mi problema hasta cierto punto. Actualmente el cliente está usando Oracle; así que si se me ocurre una solución solo para Oracle, eso funcionará [por el momento]. :)
Swaranga Sarma
66
"Sí Denis, se requiere el recuento exacto. :(" - bueno, solo puedo especular. ¿El proceso de mantenimiento de db descubre que hay 42,123,876 filas en la tabla A y luego crea 42,123,876 filas vacías en la tabla B, y luego recorre la tabla A y actualice las filas en la tabla B ... ¿O es más loco que eso? ;-)
Tony Andrews
1
La transacción 2 no puede comenzar antes de que la transacción 1 se haya comprometido. Sin la actualización de "tabla de recuentos", muchas transacciones de actualización podrían ejecutarse en paralelo. Con la "tabla de recuentos", cada transacción tiene que "obtener un ticket" para actualizar su recuento. Entonces, las transacciones comienzan a hacer cola en la máquina de tickets (el planificador decide quién será el próximo en obtener un bloqueo en la tabla de conteos).
Erwin Smout
10

¿Hay una mejor manera de obtener el recuento EXACTO del número de filas de una tabla?

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á:

SELECT COUNT(*) FROM TableName

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...

Jesse Webb
fuente
10

Recibí este script de otra pregunta / respuesta de StackOverflow:

SELECT SUM(p.rows) FROM sys.partitions AS p
  INNER JOIN sys.tables AS t
  ON p.[object_id] = t.[object_id]
  INNER JOIN sys.schemas AS s
  ON s.[schema_id] = t.[schema_id]
  WHERE t.name = N'YourTableNameHere'
  AND s.name = N'dbo'
  AND p.index_id IN (0,1);

Mi tabla tiene 500 millones de registros y lo anterior devuelve en menos de 1 ms. Mientras tanto,

SELECT COUNT(id) FROM MyTable

¡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.

JakeJ
fuente
¿Se puede agregar un parámetro para que las filas cuenten con esta consulta? Ejemplo: Seleccione COUNT (1) FROM TABLENAME WHERE ColumnFiled = '1' ¿Con su consulta?
VnDevil
Esa es la cuenta: la cantidad de filas (registros) es la "cuenta" en este caso. "500 millones de registros" era un número aproximado, y "519326012" era el número exacto de filas o recuento. Filas = registros = recuento.
JakeJ
9

Puede probar esto sp_spaceused (Transact-SQL)

Muestra el número de filas, el espacio en disco reservado y el espacio en disco utilizado por una tabla, vista indizada o cola de Service Broker en la base de datos actual, o muestra el espacio en disco reservado y utilizado por toda la base de datos.

Enjambres
fuente
¿Sp_spaceused no me dará un recuento aproximado?
Swaranga Sarma
1
FYI: Esto usa sys.dm_db_partition_stats internamente
gbn
6

Si la edición de SQL Server es 2005/2008, puede usar DMV para calcular el recuento de filas en una tabla:

-- Shows all user tables and row counts for the current database 
-- Remove is_ms_shipped = 0 check to include system objects 
-- i.index_id < 2 indicates clustered index (1) or hash table (0) 
SELECT o.name, 
 ddps.row_count 
FROM sys.indexes AS i 
 INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID 
 INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID 
 AND i.index_id = ddps.index_id 
WHERE i.index_id < 2 
 AND o.is_ms_shipped = 0 
ORDER BY o.NAME 

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

Alireza Maddah
fuente
Esto es aproximado, no exacto : vea mi respuesta por favor
gbn
¿Conoces un ejemplo donde esto no es exacto? AFAIK, no depende de estadísticas actualizadas.
Alireza Maddah
5

yo suelo

select /*+ parallel(a) */  count(1) from table_name a;
Mainsh S
fuente
select / * + parallel (a) * / count (1) from
table_name a
5

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:

Declare @max int

Select @max = Row_Count
From sys.dm_db_partition_stats
Where Object_Name(Object_Id) = 'tbl_HighOrder'

Funciona muy bien y los tiempos de consulta en Management Studio son cero.

John llueve
fuente
1
FWIW, debe mencionar QUÉ proveedor de base de datos está utilizando; Creo que la declaración sería ligeramente diferente según el proveedor.
ToolmakerSteve
5

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

Antagonista de Kaliyug
fuente
5

He encontrado este buen artículo de SQL Server-HOW-TO: recuperar rápidamente precisa recuento de filas para la tabla de martijnh1lo 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:

SELECT COUNT(*) FROM Transactions 

Comentarios:

Realiza un escaneo completo de la tabla. Reduzca la velocidad en mesas grandes.

Método 2:

Consulta:

SELECT CONVERT(bigint, rows) 
FROM sysindexes 
WHERE id = OBJECT_ID('Transactions') 
AND indid < 2 

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:

SELECT CAST(p.rows AS float) 
FROM sys.tables AS tbl 
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and
idx.index_id < 2 
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) 
AND p.index_id=idx.index_id 
WHERE ((tbl.name=N'Transactions' 
AND SCHEMA_NAME(tbl.schema_id)='dbo')) 

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:

SELECT SUM (row_count) 
FROM sys.dm_db_partition_stats 
WHERE object_id=OBJECT_ID('Transactions')    
AND (index_id=0 or index_id=1); 

Comentarios:

Operación rápida (aunque no tan rápida como el método 2) e igualmente importante, confiable.

Thierry
fuente
¡Gracias! Consejo realmente útil. No tengo permiso para ver las tablas del sistema, por lo que el método 4 no soy yo. Sin embargo, el método 3 es lo suficientemente bueno.
Nicholas Humphrey
3

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.

Mike Woodhouse
fuente
Espero que cualquier DBMS decente use un índice para SELECT COUNT(*). Incluso MySQL aparentemente lo hace ....
sleske
suponiendo que no se eliminen, ¿en serio? ; p
ToolmakerSteve
3

Llego tarde a esta pregunta, pero esto es lo que puede hacer con MySQL (ya que uso MySQL). Estoy compartiendo mis observaciones aquí:

1) SELECT COUNT(*) AS TOTAL_ROWS FROM <TABLE_NAME>


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.

2) SHOW TABLE STATUS or SHOW TABLE STATUS WHERE NAME="<TABLE_NAME>"

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.

3) SELECT * FROM information_schema.tables WHERE table_schema = DATABASE();

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í.

sunitkatkar
fuente
2

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:

UPDATE T SET N = N + 1

También cree un DELETE TRIGGER que ejecute:

UPDATE T SET N = N - 1

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:

SELECT N FROM T

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.

Branko Dimitrijevic
fuente
2

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):

-- First slave
SELECT COUNT(pk) FROM t WHERE pk < 250000000
-- Ith slave where 2 <= I <= N - 1
SELECT COUNT(pk) FROM t WHERE pk >= I*250000000 and pk < (I+1)*250000000
-- Last slave
SELECT COUNT(pk) FROM t WHERE pk > (N-1)*250000000

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:

CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)

Entonces, en lugar de solo tener las selecciones ejecutándose en sus esclavos, tendría que hacer una inserción, similar a esto:

INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)

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:

-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)

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 UNIONobtener todas las filas que necesita.

SELECT SUM(cnt) FROM (
    SELECT * FROM counter_table_slave_1
      UNION
    SELECT * FROM counter_table_slave_2
      UNION
    ...
  )

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 soloSELECT 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.

Yangmun Choi
fuente
2

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áticoid , luego de contar toda la tabla una vez y recordar el conteo como last-county last-counted-id,

entonces cada día solo necesita contar para id> last-counted-id, agregar eso last-county almacenar el nuevo last-counted-id.

El activador de eliminación disminuiría el último recuento, si la identificación del registro eliminado <= último-contado-id.

ToolmakerSteve
fuente
.. lo siento, no tengo tiempo para mostrar el SQL que se usaría (mi SQL está oxidado). Si alguien quiere editar mi respuesta para agregar SQL, ¡sería genial!
ToolmakerSteve
1

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:

SELECT TOP(1) <primarykeyfield> FROM <table> ORDER BY <primarykeyfield> DESC;

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.

KevinS
fuente
1
No del todo cierto: ¿qué sucede si INSERTse 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.
Sir Crispalot
El podría ser lagunas en secuencia. Por lo general, resultado de retrocesos.
Osa E
En realidad, hay una modificación de esta respuesta que podría ser significativamente más rápida que count(*), si un proveedor de base de datos no se ha optimizado lo suficiente count(*): 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 manejar deletes si agrega un disparador al eliminar que disminuye el total anterior , si se eliminó el ID de registro <= ese último índice automático.
ToolmakerSteve
1

Para el servidor SQL intente esto

SELECT T.name, 
       I.rows AS [ROWCOUNT] 
FROM   sys.tables AS T 
       INNER JOIN sys.sysindexes AS I 
               ON T.object_id = I.id AND I.indid < 2 
WHERE T.name = 'Your_Table_Name'
ORDER  BY I.rows DESC 
Abhishek B Patel
fuente
0

seleccione filas de sysindexes donde id = Object_ID ('TableName') e indid <2

Enzero
fuente
0

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.

EvilTeach
fuente
Si una tabla tiene miles de millones de filas sin un índice en ninguna columna, habrá problemas de rendimiento generalizados, mucho más allá de la necesidad expresada en la pregunta original ... pero es bueno que lo mencione (¡no asuma nada!) :)
ToolmakerSteve
0

Si está utilizando Oracle, ¿qué tal esto (suponiendo que las estadísticas de la tabla estén actualizadas):

select <TABLE_NAME>, num_rows, last_analyzed from user_tables

last_analyzed mostrará la hora en que se recopilaron las estadísticas por última vez.

Diogo Ferreira
fuente
0

Con PostgreSQL:

SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = 'table_name'
dorio
fuente
-1

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.

SenSei
fuente
Estaba buscando a 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 (*)
Frieder
-3

Tal vez un poco tarde, pero esto podría ayudar a otros para MSSQL

; CON RecordCount AS (SELECT ROW_NUMBER () OVER (ORDER BY COLUMN_NAME) AS [RowNumber] FROM TABLE_NAME) SELECT MAX (RowNumber) FROM RecordCount

Justus Swanevelder
fuente
Esto es significativamente PEOR que COUNT (), a menos que tengamos MUCHA suerte y el optimizador logre optimizarlo en COUNT (), ¿por qué pedirlo a SORT en una columna aleatoria?
dsz