Postgres: count (*) vs count (id)


11

Ho visto nella documentazione la differenza tra count(*)e count(pk). Stavo usando count(pk)(dov'è pka SERIAL PRIMARY KEY) non sapendo dell'esistenza di count(*).

La mia domanda riguarda le ottimizzazioni interne di Postgres. È abbastanza intelligente capire che SERIAL PRIMARY KEYa esisterà in ogni riga e non sarà mai falso e conterà solo le righe o eseguirà controlli predicati ridondanti per ogni riga? Concordo sul fatto che probabilmente si tratta di un'ottimizzazione troppo inutile, ma sono solo curioso.

Ho dato un'occhiata all'output di EXPLAINe EXPLAIN VERBOSEper count(*), count(id)e count(id > 50)per vedere se EXPLAINmenzionato controllando i predicati nel suo output. Non

Risposte:


15

Ho ottenuto risultati coerenti nei miei test ripetuti con varie versioni negli ultimi anni:
count(*)è leggermente più veloce di count(pk). È anche più corto e il più delle volte si adatta meglio a ciò che viene testato: l'esistenza di una riga.

Per quanto riguarda:

Postgres è abbastanza intelligente da capire che SERIAL PRIMARY KEYa esisterà in ogni riga e non sarà mai falso

L'unica cosa rilevante è il NOT NULLvincolo. Il PRIMARY KEYè NOT NULLautomaticamente, serialo never falsesono ortogonali alla domanda.

Con count(col), se PostgreSQL stava cercando di essere intelligente e controllare il catalogo di sistema se una colonna fosse NOT NULLe tornare a un equivalente count(*), avresti comunque una ricerca in più su una tabella di sistema rispetto a count(*).

Per quanto riguarda EXPLAINl'uscita, non v'è un suggerimento:

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) ...

Significato, noncount(col) viene convertito in , anche se è definito .count(*)NOT NULL


È ancora il caso delle nuove versioni? Penso che non avrebbe davvero bisogno di una ricerca per ogni query - potrebbe essere memorizzato nella cache.
Ondra Žižka,

1
A proposito, con una NOT NULLcolonna, la differenza è grande se hai molte righe. Nel nostro caso con milioni di righe, COUNT(*)è 3 volte più veloce. (Postgres 9.4)
Ondra Žižka,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.