web-dev-qa-db-fra.com

Postgres: Comptez (*) VS Count (ID)

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.

11
ldrg

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.

15
Erwin Brandstetter