Thilo har fundet forskellen præcist... COUNT( column_name )
kan returnere et lavere tal end COUNT( * )
hvis column_name
kan være NULL
.
Men hvis jeg kan tage en lidt anden vinkel på at besvare dit spørgsmål, da du ser ud til at fokusere på ydeevne.
Bemærk først, at udsendelse af SELECT COUNT(*) FROM table;
vil potentielt blokere forfattere, og det vil også blive blokeret af andre læsere/skribenter, medmindre du har ændret isolationsniveauet (knæstød har en tendens til at være WITH (NOLOCK)
men jeg ser, at et lovende antal mennesker endelig begynder at tro på RCSI). Hvilket betyder, at mens du læser dataene for at få din "nøjagtige" optælling, hober alle disse DML-anmodninger op, og når du endelig har frigivet alle dine låse, åbner sluserne sig, en masse indsæt/opdater/slet aktivitet sker, og der går din "præcise" optælling.
Hvis du har brug for en absolut transaktionsmæssigt konsistent og nøjagtig rækketælling (selvom den kun er gyldig i det antal millisekunder, det tager at returnere tallet til dig), så SELECT COUNT( * )
er dit eneste valg.
På den anden side, hvis du forsøger at få en 99,9 % nøjagtig boldbane, er du meget bedre stillet med en forespørgsel som denne:
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);
(SUM
er der for at tage højde for partitionerede tabeller - hvis du ikke bruger tabelpartitionering, kan du udelade det.)
Denne DMV opretholder nøjagtige rækketællinger for tabeller med undtagelse af rækker, der i øjeblikket deltager i transaktioner - og netop disse transaktioner er dem, der vil gøre din SELECT COUNT
forespørgsel vent (og i sidste ende gøre det unøjagtigt, før du når at læse det). Men ellers vil dette føre til et meget hurtigere svar end den forespørgsel, du foreslår, og ikke mindre præcis end at bruge WITH (NOLOCK)
.