Un aproximado muy cercano (ignorando cualquier transacción en vuelo) sería:
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'myTable'
AND s.name = N'dbo'
AND p.index_id IN (0,1);
Esto devolverá mucho, mucho más rápido que COUNT(*)
, y si su tabla está cambiando lo suficientemente rápido, en realidad no es menos precisa:si su tabla ha cambiado entre el momento en que inició su COUNT (y se tomaron los bloqueos) y cuando se devolvió (cuando se liberaron los bloqueos y todas las transacciones de escritura en espera ahora se les permitía escribir en la mesa), ¿es mucho más valioso? No lo creo.
Si tiene algún subconjunto de la tabla que desea contar (digamos, WHERE some_column IS NULL
), podría crear un índice filtrado en esa columna y estructurar la cláusula where de una forma u otra, dependiendo de si era la excepción o la regla (así que cree el índice filtrado en el conjunto más pequeño). Así que uno de estos dos índices:
CREATE INDEX IAmTheException ON dbo.table(some_column)
WHERE some_column IS NULL;
CREATE INDEX IAmTheRule ON dbo.table(some_column)
WHERE some_column IS NOT NULL;
Entonces podrías obtener el conteo de manera similar usando:
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]
INNER JOIN sys.indexes AS i
ON p.index_id = i.index_id
WHERE t.name = N'myTable'
AND s.name = N'dbo'
AND i.name = N'IAmTheException' -- or N'IAmTheRule'
AND p.index_id IN (0,1);
Y si quieres saber lo contrario, simplemente resta de la primera consulta anterior.