Approssimativamente molto vicino (ignorando qualsiasi transazione in volo) sarebbe:
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);
Questo ritornerà molto, molto più velocemente di COUNT(*)
, e se la tua tabella sta cambiando abbastanza velocemente, non è davvero per niente meno precisa - se la tua tabella è cambiata tra quando hai iniziato il tuo COUNT (e sono stati presi i blocchi) e quando è stato restituito (quando sono stati rilasciati i blocchi e tutte le transazioni di scrittura in attesa erano ora autorizzati a scrivere al tavolo), è molto più prezioso? Non credo.
Se hai qualche sottoinsieme della tabella che vuoi contare (diciamo, WHERE some_column IS NULL
), potresti creare un indice filtrato su quella colonna e strutturare la clausola where in un modo o nell'altro, a seconda che fosse l'eccezione o la regola (quindi crea l'indice filtrato sull'insieme più piccolo). Quindi uno di questi due indici:
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;
Quindi potresti ottenere il conteggio in modo simile utilizzando:
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);
E se vuoi sapere il contrario, devi semplicemente sottrarre dalla prima query sopra.