J'ai vu dans la documentation la différence entre count(*)
et count(pk)
. J'avais utilisé count(pk)
(où pk
est un SERIAL PRIMARY KEY
) Ne connaît pas l'existence de count(*)
.
Ma question concerne les optimisations internes des postgres. Est-il assez intelligent de ramasser qu'un SERIAL PRIMARY KEY
Va exister dans chaque rangée et ne jamais être faux et ne comptez que compter des lignes ou fera-t-elle des contrôles de prédicats redondants pour chaque ligne? Je conviens que cela est probablement trop d'une optimisation inutile, mais je suis juste curieux.
J'ai examiné la sortie de EXPLAIN
et EXPLAIN VERBOSE
Pour count(*)
, count(id)
et count(id > 50)
pour voir si EXPLAIN
mentionné vérifier les prédicats dans sa sortie. Ce n'est pas le cas.
J'ai eu des résultats cohérents dans mes tests répétés avec diverses versions au cours des dernières années:count(*)
est légèrement plus rapide que count(pk)
. Il est également plus court et la plupart du temps, il est préférable d'obtenir ce qui est testé: l'existence d'une ligne.
Concernant:
Est-ce que Postgres est assez intelligent pour ramasser que un
SERIAL PRIMARY KEY
Va exister dans chaque rangée et ne jamais être faux
La seule chose pertinente est la contrainte de NOT NULL
. Le PRIMARY KEY
Est NOT NULL
Automatiquement, serial
ou never false
Sont orthogonaux à la question.
Avec count(col)
, si PostgreSQL essayait d'être intelligent et de vérifier le catalogue système si une colonne était NOT NULL
Et Revenez à un équivalent count(*)
, vous auriez toujours une recherche de plus sur une table système qu'avec count(*)
.
Quant à EXPLAIN
sortie, il est un indice:
EXPLAIN SELECT count(*) FROM ...
Aggregate (cost=4963.38..4963.43 rows=1 width=0) ...
EXPLAIN SELECT count(pk) FROM ...
Aggregate (cost=4963.38..4963.43 rows=1 width=4) ...
Signification, count(col)
est non converti en count(*)
, même s'il est défini NOT NULL
.