Thilo ha individuato la differenza con precisione... COUNT( column_name )
può restituire un numero inferiore a COUNT( * )
se column_name
può essere NULL
.
Tuttavia, se posso rispondere alla tua domanda da un punto di vista leggermente diverso, dal momento che sembri concentrarti sulle prestazioni.
Innanzitutto, nota che emettendo SELECT COUNT(*) FROM table;
bloccherà potenzialmente gli scrittori e sarà anche bloccato da altri lettori/scrittori a meno che tu non abbia alterato il livello di isolamento (l'effetto a scatti tende ad essere WITH (NOLOCK)
ma vedo un numero promettente di persone che finalmente iniziano a credere in RCSI). Ciò significa che mentre leggi i dati per ottenere il tuo conteggio "accurato", tutte queste richieste DML si stanno accumulando e quando hai finalmente rilasciato tutti i tuoi blocchi, le porte si aprono, un mucchio di inserimenti/aggiornamenti/eliminazioni si verifica l'attività e il conteggio "preciso".
Se hai bisogno di un conteggio delle righe assolutamente coerente e accurato dal punto di vista transazionale (anche se è valido solo per il numero di millisecondi necessari per restituirti il numero), allora SELECT COUNT( * )
è la tua unica scelta.
D'altra parte, se stai cercando di ottenere un campo di gioco accurato al 99,9%, stai molto meglio con una query come questa:
SELECT row_count = SUM(row_count)
FROM sys.dm_db_partition_stats
WHERE [object_id] = OBJECT_ID('dbo.Table')
AND index_id IN (0,1);
(La SUM
è lì per tenere conto delle tabelle partizionate:se non stai utilizzando il partizionamento delle tabelle, puoi ometterlo.)
Questo DMV mantiene conteggi accurati delle righe per le tabelle ad eccezione delle righe che stanno attualmente partecipando alle transazioni - e quelle stesse transazioni saranno quelle che renderanno il tuo SELECT COUNT
query wait (e alla fine rendilo impreciso prima di avere il tempo di leggerlo). Ma altrimenti questo porterà a una risposta molto più rapida rispetto alla domanda che proponi e non meno accurata dell'utilizzo di WITH (NOLOCK)
.