Много близко приблизително (без да се вземат предвид всички транзакции по време на полет) би било:
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);
Това ще върне много, много по-бързо от COUNT(*)
, и ако вашата таблица се променя достатъчно бързо, тя всъщност не е по-малко точна - ако вашата таблица се е променила между момента, в който сте започнали своя БРОЙ (и са били взети заключвания) и когато е била върната (когато заключванията са били освободени и всички чакащи транзакции за запис сега им беше позволено да пишат в таблицата), толкова ли е по-ценно? Не мисля така.
Ако имате някакво подмножество от таблицата, което искате да преброите (да речем, WHERE some_column IS NULL
), бихте могли да създадете филтриран индекс в тази колона и да структурирате клаузата where по един или друг начин, в зависимост от това дали е изключение или правило (така че създайте филтрирания индекс върху по-малкия набор). Така един от тези два индекса:
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;
След това можете да получите броя по подобен начин, като използвате:
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);
И ако искате да знаете обратното, просто извадете от първото запитване по-горе.