Mycket nära ungefärlig (om man ignorerar eventuella transaktioner under flygning) skulle vara:
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);
Detta kommer att returnera mycket, mycket snabbare än COUNT(*)
, och om din tabell ändras tillräckligt snabbt, är den egentligen inte mindre exakt - om din tabell har ändrats mellan när du startade din COUNT (och lås togs) och när den returnerades (när lås släpptes och alla väntande skrivtransaktioner fick nu skriva till bordet), är det så mycket mer värdefullt? Jag tror inte det.
Om du har någon delmängd av tabellen som du vill räkna (säg, WHERE some_column IS NULL
), kan du skapa ett filtrerat index på den kolumnen och strukturera where-satsen på ett eller annat sätt, beroende på om det var undantaget eller regeln (så skapa det filtrerade indexet på den mindre uppsättningen). Så ett av dessa två index:
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;
Då kan du få räkningen på ett liknande sätt med:
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);
Och om du vill veta motsatsen, subtraherar du bara från den första frågan ovan.