Thilo a bien compris la différence... COUNT( column_name )
peut renvoyer un nombre inférieur à COUNT( * )
si column_name
peut être NULL
.
Cependant, si je peux prendre un angle légèrement différent pour répondre à votre question, puisque vous semblez vous concentrer sur les performances.
Tout d'abord, notez que l'émission de SELECT COUNT(*) FROM table;
bloquera potentiellement les écrivains, et il sera également bloqué par d'autres lecteurs/écrivains à moins que vous n'ayez modifié le niveau d'isolement (le réflexe a tendance à être WITH (NOLOCK)
mais je vois un nombre prometteur de personnes qui commencent enfin à croire au RCSI). Ce qui signifie que pendant que vous lisez les données pour obtenir votre décompte "précis", toutes ces requêtes DML s'accumulent, et lorsque vous avez enfin libéré tous vos verrous, les vannes s'ouvrent, un tas d'insertions/mises à jour/suppressions l'activité se produit, et voilà votre décompte "précis".
Si vous avez besoin d'un nombre de lignes absolument cohérent et précis sur le plan transactionnel (même s'il n'est valide que pour le nombre de millisecondes nécessaires pour vous renvoyer le nombre), alors SELECT COUNT( * )
est votre seul choix.
D'un autre côté, si vous essayez d'obtenir une approximation précise à 99,9 %, vous feriez mieux d'utiliser une requête comme celle-ci :
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
est là pour tenir compte des tables partitionnées - si vous n'utilisez pas le partitionnement de table, vous pouvez l'omettre.)
Ce DMV maintient un nombre de lignes précis pour les tables à l'exception des lignes qui participent actuellement aux transactions - et ces mêmes transactions sont celles qui feront de votre SELECT COUNT
query wait (et finalement la rendre inexacte avant d'avoir le temps de la lire). Mais sinon, cela conduira à une réponse beaucoup plus rapide que la requête que vous proposez, et non moins précise que l'utilisation de WITH (NOLOCK)
.