Postgres: cuenta (*) vs cuenta (id)


11

Vi en la documentación la diferencia entre count(*)y count(pk). Había estado usando count(pk)(donde pkestá a SERIAL PRIMARY KEY) sin saber sobre la existencia de count(*).

Mi pregunta es sobre las optimizaciones internas de Postgres. ¿Es lo suficientemente inteligente como para darse cuenta de que SERIAL PRIMARY KEYa existirá en cada fila y nunca será falso y solo contará filas o hará verificaciones redundantes de predicados para cada fila? Estoy de acuerdo en que esta es probablemente una optimización demasiado inútil, pero tengo curiosidad.

Eché un vistazo a la salida de EXPLAINy EXPLAIN VERBOSEpara count(*), count(id)y count(id > 50)para ver si EXPLAINmencionó verificar los predicados en su salida. No lo hace.

Respuestas:


15

Obtuve resultados consistentes en mis repetidas pruebas con varias versiones en los últimos años:
count(*)es un poco más rápido que count(pk). También es más corto y la mayoría de las veces se ajusta mejor a lo que se prueba: la existencia de una fila.

Sobre:

¿Es Postgres lo suficientemente inteligente como para darse cuenta de que SERIAL PRIMARY KEYa existirá en cada fila y nunca será falso?

Lo único relevante es la NOT NULLrestricción. El PRIMARY KEYes NOT NULLautomáticamente, serialo never falseson ortogonales a la pregunta.

Con count(col), si PostgreSQL intentaba ser inteligente y comprobar el catálogo del sistema si era una columna NOT NULLy recurrir a un equivalente count(*), aún tendría una búsqueda más en una tabla del sistema que con count(*).

En cuanto a EXPLAINla producción, no es una pista:

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

Es decir, count(col)se no se convierte en count(*), incluso si está definido NOT NULL.


¿Sigue siendo el caso con las nuevas versiones? Creo que realmente no necesitaría una búsqueda para cada consulta, podría almacenarse en caché.
Ondra Žižka

1
Por cierto, con una NOT NULLcolumna, la diferencia es grande si tienes muchas filas. En nuestro caso con millones de filas, COUNT(*)es 3 veces más rápido. (Postgres 9.4)
Ondra Žižka
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.