COUNT(*)

Le mot clé COUNT correspondant à une fonction d’agrégation permettant de comptabiliser le nombre d’enregistrements d’un jeu de résultats. Toutefois, lorsqu’il s’agit simplement de connaître le nombre d’enregistrements d’une table, il y a bien plus rapide et plus efficace…
Dans les exemples ci-après, nous nous appuierons sur la base de données AdventureWorks, disponible à l’adresse http://msftdbprodsamples.codeplex.com/.
Lorsqu’il s’agit de compter le nombre d’enregistrements de la table Sales.SalesOrderDetail, le premier réflexe consiste à utiliser la fonction COUNT.

select COUNT(*) from Sales.SalesOrderDetail

Mais dès lors que la table est un peu volumineuse, on s’aperçoit que cette instruction prend pas mal de temps et de ressources.
Table ‘SalesOrderDetail’. Nombre d’analyses 1, lectures logiques 229, lectures physiques 0, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.

Pour plus d’efficacité, quelques tables système présentes depuis SQL Server 2005 permettent d’obtenir de manière beaucoup plus rapide la réponse demandée.

select sum(rows)
from sys.partitions p
	join sys.indexes i on i.object_id=p.object_id and p.index_id=i.index_id
	join sys.objects o on o.object_id=i.object_id
	join sys.schemas s on s.schema_id=o.schema_id
where i.index_id in (0,1) --0 si la table n'a pas d'index clustered, 1 si elle en a un
	and o.name='SalesOrderDetail'
	and s.name='Sales'

Table ‘Worktable’. Nombre d’analyses 0, lectures logiques 0, lectures physiques 0, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.
Table ‘sysrowsets’. Nombre d’analyses 1, lectures logiques 5, lectures physiques 1, lectures anticipées 15, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.
Table ‘sysidxstats’. Nombre d’analyses 2, lectures logiques 4, lectures physiques 0, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.
Table ‘sysschobjs’. Nombre d’analyses 0, lectures logiques 4, lectures physiques 1, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.
Table ‘sysclsobjs’. Nombre d’analyses 0, lectures logiques 2, lectures physiques 0, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.

On voit que le nombre de lectures logiques est nettement plus réduit, et surtout il serait inchangé même si la table contenait un nombre d’enregistrements nettement plus important. Ainsi, chargeons une table de test avec 10 000 000 enregistrements assez volumineux.

use tempdb
set nocount on
go
create table dbo.TestComptage (Id int identity primary key,
							Donnee nchar(1000) DEFAULT 'Valeur de test')
GO
INSERT INTO dbo.TestComptage (Donnee) VALUES (DEFAULT)
GO 10000000

Pour cette table de tests, voici les différents résultats de durée du comptage du nombre d’enregistrements (le résultat est sans appel !) :
Avec la méthode COUNT(*) :
/*————————
select COUNT(*) from dbo.TestComptage
————————*/
Temps d’analyse et de compilation de SQL Server :
, Temps UC = 0 ms, temps écoulé = 3 ms.

———–
10000000

Table ‘TestComptage’. Nombre d’analyses 4, lectures logiques 2510800, lectures physiques 8329, lectures anticipées 1936602, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.

SQL Server \endash Temps d’exécution :
, Temps UC = 16594 ms, temps écoulé = 61123 ms.
En passant par les tables système :
/*————————
select sum(rows)
from sys.partitions p
join sys.indexes i on i.object_id=p.object_id and p.index_id=i.index_id
join sys.objects o on o.object_id=i.object_id
join sys.schemas s on s.schema_id=o.schema_id
where i.index_id in (0,1) –0 si la table n’a pas d’index clustered, 1 si elle en a un
and o.name=’TestComptage’
and s.name=’dbo’
————————*/
Temps d’analyse et de compilation de SQL Server :
, Temps UC = 0 ms, temps écoulé = 0 ms.

——————–
10000000

Table ‘sysclsobjs’. Nombre d’analyses 0, lectures logiques 2, lectures physiques 0, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.
Table ‘sysidxstats’. Nombre d’analyses 0, lectures logiques 2, lectures physiques 0, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.
Table ‘sysschobjs’. Nombre d’analyses 0, lectures logiques 110, lectures physiques 0, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.
Table ‘sysrowsets’. Nombre d’analyses 1, lectures logiques 2, lectures physiques 0, lectures anticipées 0, lectures logiques de données d’objets volumineux 0, lectures physiques de données d’objets volumineux 0, lectures anticipées de données d’objets volumineux 0.

SQL Server \endash Temps d’exécution :
, Temps UC = 0 ms, temps écoulé = 0 ms.

A noter aussi que cette manière de compter le nombre de lignes peut aussi être intéressante pour les tables n’ayant pas énormément d’enregistrements. En effet, même si la durée et les I/O gagnés ne sont dans ce cas pas forcément énormes en temps normal, la méthode consistant à passer par les tables système n’est pas sensible aux verrous, et il est donc possible de compter les lignes même si certains enregistrements sont verrouillés par d’autres processus…

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Etes-vous un robot ? *Chargement du capcha...

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.