Isso está relacionado à contagem do número de registros que correspondem a uma determinada condição, por exemplo, invoice amount > $100
.
eu costumo preferir
COUNT(CASE WHEN invoice_amount > 100 THEN 1 END)
No entanto, isso é tão válido
SUM(CASE WHEN invoice_amount > 100 THEN 1 ELSE 0 END)
Eu teria pensado que COUNT é preferível por 2 razões:
- Transmite a intenção, que é
COUNT
COUNT
provavelmente envolve umai += 1
operação simples em algum lugar, enquanto SUM não pode contar com sua expressão como um valor inteiro simples.
Alguém tem fatos específicos sobre a diferença em RDBMS específicos?
Na maioria das vezes você mesmo já respondeu a pergunta. Tenho alguns detalhes a acrescentar:
No PostgreSQL (e outros RDBMS que suportam o
boolean
tipo) você pode usar oboolean
resultado do teste diretamente. Transmita parainteger
eSUM()
:Ou use-o em uma
NULLIF()
expressão eCOUNT()
:Ou com um simples
OR NULL
:Ou várias outras expressões. O desempenho é quase idêntico .
COUNT()
é tipicamente um pouco mais rápido queSUM()
. Ao contrárioSUM()
e como o Paul já comentou ,COUNT()
nunca mais voltaNULL
, o que pode ser conveniente. Relacionado:Desde o Postgres 9.4 também existe a
FILTER
cláusula agregada . Ver:É mais rápido do que todos os itens acima em cerca de 5 a 10%:
Se a consulta for tão simples quanto seu caso de teste, com apenas uma única contagem e nada mais, você poderá reescrever:
... que é o verdadeiro rei do desempenho, mesmo sem índice.
Com um índice aplicável, pode ser mais rápido em ordens de magnitude, especialmente com varreduras somente de índice.
Referências
Postgres 13
db<>fique aqui
Basicamente os mesmos resultados do Postgres 10 abaixo. (Também adicionei um teste sem o novo paralelismo ao violino, para comparar maçãs com maçãs.)
Postgres 10
Executei uma nova série de testes para o Postgres 10, incluindo a
FILTER
cláusula agregada e demonstrando o papel de um índice para pequenas e grandes contagens.Configuração simples:
Os tempos reais variam um pouco devido ao ruído de fundo e às especificidades da bancada de teste. Mostrando os melhores tempos típicos de um conjunto maior de testes. Esses dois casos devem capturar a essência:
Teste 1 contando ~ 1% de todas as linhas
db<>fique aqui
Teste 2 contando ~ 33% de todas as linhas
db<>fique aqui
O último teste em cada conjunto usou uma varredura somente de índice , razão pela qual ajudou a contar um terço de todas as linhas. As varreduras de índice simples ou de bitmap não podem competir com uma varredura sequencial quando envolvem aproximadamente 5% ou mais de todas as linhas.
Teste antigo para o Postgres 9.1
Para verificar fiz um teste rápido com
EXPLAIN ANALYZE
uma tabela da vida real no PostgreSQL 9.1.6.74208 de 184568 linhas qualificadas com a condição
kat_id > 50
. Todas as consultas retornam o mesmo resultado. Eu executei cada uma 10 vezes em turnos para excluir os efeitos de cache e anexei o melhor resultado como nota:Quase nenhuma diferença real no desempenho.
Este é o meu teste no SQL Server 2012 RTM.
Olhando para execuções e lotes individuais separadamente
Os resultados depois de executar 5 vezes (e repetir) são bastante inconclusivos.
Isso mostra que há muito mais variabilidade nas condições de execução do que diferença entre a implementação, quando medida com a granularidade do timer do SQL Server. Qualquer uma das versões pode vir no topo, e a variância máxima que já obtive é de 2,5%.
No entanto, adotando uma abordagem diferente:
StmtText (SOMA)
StmtText (COUNT)
Da minha leitura, parece que a versão SUM faz um pouco mais. Ele está realizando um COUNT além de um SUM. Dito isto,
COUNT(*)
é diferente e deve ser mais rápido queCOUNT([Expr1004])
(pular NULLs, mais lógica). Um otimizador razoável perceberá que[Expr1004]
naSUM([Expr1004])
versão SUM é um tipo "int" e, portanto, utilizará um registro inteiro.De qualquer forma, embora eu ainda acredite que a
COUNT
versão será mais rápida na maioria dos RDBMS, minha conclusão dos testes é que vou continuarSUM(.. 1.. 0..)
no futuro, pelo menos para o SQL Server por nenhum outro motivo além dos ANSI WARNINGS sendo levantados ao usarCOUNT
.Em Minha experiência Fazendo um rastreamento, para ambos os métodos em uma consulta de cerca de 10.000.000, notei que Count(*) usa cerca de duas vezes a CPU e roda um pouco mais rápido. mas minhas consultas estão sem filtro.
Contar(*)
Soma(1)