Tifox a dit:
Dans tout les cas, le count(*) a été plus rapide (un poil ou beaucoup) que count(id) ou count (nom_d'un_champs).
COUNT(*) sera systématiquement plus rapide, parce qu'il n'a pas la même signification que Count(field).
COUNT(*) a une signification spéciale : il renvoie la cardinalité de la table, c'est à dire le nombre de lignes.
COUNT(field) renvoie le nombre d'enregistrements où field est non nul, ça revient à "COUNT(*) WHERE field IS NOT NULL".
C'est plus long parce que pas mal de moteurs de bases de données (comme MySQL) cachent le nombre de lignes d'une table, ils n'ont donc pas besoin d'éxécuter la requête. Pour COUNT(id), si il ne sont pas transactionnels et qu'il y a un index sur id, ils se contentent de compter les enregistrements dans l'index, ça reste donc très rapide.
Pas mal de SGBD transactionnels ont aussi des informations de transaction dans les index, du coup ils peuvent aussi optimiser les COUNT.
PostgreSQL est un cas très spécial dans le monde des SGBD car il ne cache pas le nombre de lignes. C'est dû au fait qu'il soit fortement axé sur les transactions.
Ses index ne contiennent pas d'information de transaction, donc PostgreSQL ne peut pas se baser sur eux pour compter ni le nombre de lignes, ni le nombre de lignes non nulles : il est obligé de parcourir toute la table !
Conséquence directe : COUNT(*) est très lent dans PostgreSQL, et prend exactement le même temps que COUNT(field).
EXPLAIN ANALYZE
SELECT COUNT(*)
FROM nw
WHERE frc=1;
"Aggregate (
cost=693583.64..693583.65 rows=1 width=0) (actual time=335830.861..335830.861 rows=1 loops=1)"
" -> Bitmap Heap Scan on nw (cost=5716.58..692820.62 rows=305210 width=0) (actual time=447.847..335715.959 rows=314909 loops=1)"
" Recheck Cond: (frc = 1)"
" -> Bitmap Index Scan on nw_frc_btree (cost=0.00..5640.28 rows=305210 width=0) (actual time=361.512..361.512 rows=314909 loops=1)"
" Index Cond: (frc = 1)"
"Total runtime: 335831.777 ms"
EXPLAIN ANALYZE
SELECT COUNT(gid)
FROM nw
WHERE frc=1;
"Aggregate (
cost=693583.64..693583.65 rows=1 width=4) (actual time=539638.289..539638.290 rows=1 loops=1)"
" -> Bitmap Heap Scan on nw (cost=5716.58..692820.62 rows=305210 width=4) (actual time=1074.860..539482.828 rows=314909 loops=1)"
" Recheck Cond: (frc = 1)"
" -> Bitmap Index Scan on nw_frc_btree (cost=0.00..5640.28 rows=305210 width=0) (actual time=988.216..988.216 rows=314909 loops=1)"
" Index Cond: (frc = 1)"
"Total runtime: 539639.177 ms"
COUNT(gid) reste un peu plus cher, parce qu'il faut regarder la valeur du champ pour savoir si il est nul, d'où le "width=4", alors qu'avec COUNT(*) width=0.