Eu vi na documentação a diferença entre count(*)
e count(pk)
. Eu estava usando count(pk)
(onde pk
está um SERIAL PRIMARY KEY
) sem saber da existência de count(*)
.
Minha pergunta é sobre as otimizações internas do Postgres. É inteligente o suficiente para perceber que SERIAL PRIMARY KEY
a existirá em todas as linhas e nunca será falso e apenas contará as linhas ou fará verificações redundantes de predicados para cada linha? Eu concordo que isso provavelmente é uma otimização sem sentido, mas estou apenas curioso.
Dei uma olhada na saída de EXPLAIN
e EXPLAIN VERBOSE
para count(*)
, count(id)
e count(id > 50)
para ver se EXPLAIN
mencionei a verificação dos predicados em sua saída. Não.
Obtive resultados consistentes em meus testes repetidos com várias versões nos últimos anos:
count(*)
é mais rápido quecount(pk)
. Também é mais curto e na maioria das vezes se ajusta melhor ao que é testado: a existência de uma linha.Relativo:
A única coisa relevante é a
NOT NULL
restrição. UmaPRIMARY KEY
coluna éNOT NULL
automaticamente. "serial" ou "nunca falso" são ortogonais à pergunta.Com
count(col)
, se o PostgreSQL estivesse tentando ser inteligente e verificar o catálogo do sistema se uma coluna eraNOT NULL
e voltar para um equivalentecount(*)
, você ainda teria uma pesquisa a mais em uma tabela do sistema do que comcount(*)
.Além do mais, qualquer coluna pode conter
NULL
valores após umOUTER JOIN
. Portanto, a otimização não é aplicável a determinadas consultas. Provavelmente não vale a pena a complicação ...Quanto à
EXPLAIN
saída, há uma dica:Ou seja, não
count(col)
é convertido em , mesmo que seja definido .count(*)
NOT NULL