Imaginando se algum de vocês usa Count(1)
demais Count(*)
e se há uma diferença perceptível no desempenho ou se esse é apenas um hábito herdado que foi trazido adiante desde os dias passados.
O banco de dados específico é SQL Server 2005
.
sql
sql-server
performance
super9
fonte
fonte
COUNT(*)
vsCOUNT(1)
vsCOUNT(pk)
- o que é melhor? . Há tambémCOUNT(*)
vsCOUNT(column-name)
- o que é mais correto? . Pode haver outras duplicatas.Respostas:
Não há diferença.
Razão:
"1" é uma expressão não nula: portanto, é a mesma coisa que
COUNT(*)
. O otimizador reconhece o que é: trivial.O mesmo que
EXISTS (SELECT * ...
ouEXISTS (SELECT 1 ...
Exemplo:
Mesmo IO, mesmo plano, as obras
Editar, ago 2011
Pergunta semelhante sobre DBA.SE .
Editar, dez 2011
COUNT(*)
é mencionado especificamente no ANSI-92 (procure por "Scalar expressions 125
")Ou seja, o padrão ANSI reconhece como sangramento óbvio o que você quer dizer.
COUNT(1)
foi otimizado pelos fornecedores de RDBMS por causa dessa superstição. Caso contrário, seria avaliado conforme ANSIfonte
No SQL Server, essas instruções geram os mesmos planos.
Ao contrário da opinião popular, na Oracle eles também.
SYS_GUID()
no Oracle é bastante função intensiva de computação.No meu banco de dados de teste,
t_even
há uma tabela com1,000,000
linhasEsta consulta:
é executado por
48
segundos, já que a função precisa avaliar cada umSYS_GUID()
retornado para garantir que não seja umNULL
.No entanto, esta consulta:
é executado por apenas
2
alguns segundos, já que nem tenta avaliarSYS_GUID()
(apesar de*
argumentarCOUNT(*)
)fonte
SYS_GUID()
pelo menos (quero dizer, exatamente) uma vez para a subconsulta retornar o resultado, certo?COUNT(*)
depende dos valores deSYS_GUID
?COUNT(*)
executar, ele precisa de uma tabela, então a subconsulta deve agir como uma. Caso contrário, não vejo uma maneira deCOUNT(*)
retornar um valor significativomap
método faz, você vê como essas duas expressões:t_even.map(() => sys_guid()).length
et_even.length
sempre retornaria o mesmo valor? O otimizador da Oracle é inteligente o suficiente para ver e otimizar amap
peça.length
não depende muito do que a coleção consiste, apenas do número de seus elementos. Se esse número estiver armazenado nos metadados da coleção (esse não é o caso do Oracle ou da maioria dos outros RDBMS modernos, mas o do mecanismo de armazenamento antigo do MySQL, MyISAM),COUNT(*)
seria necessário apenas pegar o valor dos metadados.Claramente,
COUNT(*)
eCOUNT(1)
irá sempre retornar o mesmo resultado. Portanto, se um fosse mais lento que o outro, seria efetivamente devido a um bug do otimizador. Como os dois formulários são usados com muita frequência em consultas, não faria sentido para um DBMS permitir que esse bug permanecesse sem correção. Portanto, você descobrirá que o desempenho de ambos os formulários é (provavelmente) idêntico em todos os principais DBMSs SQL.fonte
Trabalho na equipe do SQL Server e espero esclarecer alguns pontos deste segmento (eu não o havia visto anteriormente, então lamento que a equipe de engenharia não tenha feito isso anteriormente).
Em primeiro lugar, não há diferença entre semântica
select count(1) from table
vsselect count(*) from table
. Eles retornam os mesmos resultados em todos os casos (e é um erro, se não). Conforme observado nas outras respostas,select count(column) from table
é semanticamente diferente e nem sempre retorna os mesmos resultados quecount(*)
.Segundo, com relação ao desempenho, há dois aspectos que importariam no SQL Server (e no SQL Azure): trabalho em tempo de compilação e trabalho em tempo de execução. O trabalho de tempo de compilação é uma quantidade trivialmente pequena de trabalho extra na implementação atual. Há uma expansão do * para todas as colunas em alguns casos, seguida por uma redução de volta para 1 coluna, devido à forma como algumas das operações internas funcionam na ligação e otimização. Duvido que isso apareça em qualquer teste mensurável e provavelmente se perca no ruído de todas as outras coisas que acontecem sob as cobertas (como estatísticas automáticas, sessões xevent, sobrecarga do armazenamento de consultas, gatilhos etc.). São talvez alguns milhares de instruções extras sobre a CPU. Assim, count (1) trabalha um pouco menos durante a compilação (o que geralmente acontece uma vez e o plano é armazenado em cache em várias execuções subseqüentes). Para o tempo de execução, assumindo que os planos sejam os mesmos, não deve haver diferença mensurável. (Um dos exemplos anteriores mostra uma diferença - provavelmente é devido a outros fatores na máquina se o plano for o mesmo).
Sobre como o plano pode ser potencialmente diferente. É extremamente improvável que isso aconteça, mas é potencialmente possível na arquitetura do otimizador atual. O otimizador do SQL Server funciona como um programa de pesquisa (pense: programa de computador jogando xadrez pesquisando várias alternativas para diferentes partes da consulta e custando as alternativas para encontrar o plano mais barato em tempo razoável). Essa pesquisa possui alguns limites sobre como ela opera para manter a compilação de consultas concluída em tempo razoável. Para consultas além das mais triviais, há fases da pesquisa e elas lidam com trechos de consultas com base no quão caro o otimizador pensa que a consulta é potencialmente executada. Existem três fases principais de pesquisa e cada fase pode executar heurísticas mais agressivas (caras), tentando encontrar um plano mais barato do que qualquer solução anterior. Por fim, existe um processo de decisão no final de cada fase que tenta determinar se deve retornar o plano encontrado até agora ou se deve continuar pesquisando. Esse processo usa o tempo total gasto até agora em relação ao custo estimado do melhor plano encontrado até o momento. Portanto, em máquinas diferentes com velocidades diferentes de CPUs, é possível (embora raro) obter planos diferentes devido ao tempo limite excedido em uma fase anterior com um plano e continuar na próxima fase de pesquisa. Existem também alguns cenários semelhantes relacionados ao tempo limite da última fase e à falta de memória em consultas muito caras que consomem toda a memória da máquina (geralmente não é um problema em 64 bits, mas era uma preocupação maior). de volta em servidores de 32 bits). Por fim, se você obtiver um plano diferente, o desempenho no tempo de execução será diferente. Eu não'
Net-net: use o que você quiser, pois nada disso importa em nenhuma forma prática. (Existem fatores muito, muito maiores, que afetam o desempenho no SQL além deste tópico, honestamente).
Eu espero que isso ajude. Escrevi um capítulo de livro sobre como o otimizador funciona, mas não sei se é apropriado publicá-lo aqui (já que ainda recebo pequenos royalties dele). Então, em vez de postar, postarei um link em uma palestra que fiz no SQLBits no Reino Unido sobre como o otimizador funciona em um nível alto, para que você possa ver as diferentes fases principais da pesquisa com mais detalhes, se desejar para aprender sobre isso. Aqui está o link do vídeo: https://sqlbits.com/Sessions/Event6/inside_the_sql_server_query_optimizer
fonte
1
também passa pela mesma expansão. Baseio esta nos testes perf aqui stackoverflow.com/questions/1597442/... também ver o exemplo em que a resposta de uma consulta usando1
falhando inesperadamente quando permissões de nível de coluna estão em jogoNo padrão SQL-92,
COUNT(*)
significa especificamente "a cardinalidade da expressão da tabela" (pode ser uma tabela base, `VIEW, tabela derivada, CTE, etc).Acho que a ideia era
COUNT(*)
fácil de analisar. O uso de qualquer outra expressão requer que o analisador garanta que não faça referência a nenhuma coluna (COUNT('a')
ondea
é literal eCOUNT(a)
ondea
está uma coluna pode produzir resultados diferentes).Na mesma linha,
COUNT(*)
pode ser facilmente escolhido por um codificador humano familiarizado com os Padrões SQL, uma habilidade útil ao trabalhar com mais de uma oferta de SQL de um fornecedor.Além disso, no caso especial
SELECT COUNT(*) FROM MyPersistedTable;
, o pensamento é que o DBMS provavelmente manterá estatísticas para a cardinalidade da tabela.Portanto, porque
COUNT(1)
eCOUNT(*)
são semanticamente equivalentes, eu usoCOUNT(*)
.fonte
COUNT(*)
eCOUNT(1)
são iguais em caso de resultado e desempenho.fonte
Espero que o otimizador garanta que não haja diferença real fora dos casos extremos.
Como com qualquer coisa, a única maneira real de dizer é medir seus casos específicos.
Dito isto, eu sempre usei
COUNT(*)
.fonte
Como essa pergunta surge repetidamente, aqui está mais uma resposta. Espero adicionar algo para iniciantes que se perguntam sobre as "melhores práticas" aqui.
SELECT COUNT(*) FROM something
conta registros, o que é uma tarefa fácil.SELECT COUNT(1) FROM something
recupera 1 por registro e depois conta os 1s que não são nulos, o que é essencialmente contando registros, apenas mais complicado.Dito isto: Os bons dbms observam que a segunda instrução resultará na mesma contagem que a primeira e a interpretará de acordo, para não realizar trabalhos desnecessários. Portanto, geralmente as duas instruções resultam no mesmo plano de execução e levam a mesma quantidade de tempo.
No entanto, do ponto de legibilidade, você deve usar a primeira instrução. Você deseja contar registros, portanto, conte registros, não expressões. Use COUNT (expressão) apenas quando desejar contar ocorrências não nulas de algo.
fonte
Fiz um teste rápido no SQL Server 2012 em uma caixa hyper-v de 8 GB de RAM. Você pode ver os resultados por si mesmo. Eu não estava executando nenhum outro aplicativo em janela além do SQL Server Management Studio durante a execução desses testes.
Meu esquema de tabela:
Número total de registros na
Employee
tabela: 178090131 (~ 178 milhões de linhas)Primeira consulta:
Resultado da primeira consulta:
Segunda consulta:
Resultado da Segunda Consulta:
Você pode notar que há uma diferença de 83 (= 70265 - 70182) milissegundos que pode ser facilmente atribuída à condição exata do sistema no momento em que as consultas são executadas. Também fiz uma única execução, portanto essa diferença se tornará mais precisa se eu fizer várias e fizer uma média. Se, para um conjunto de dados tão grande, a diferença chegar a menos de 100 milissegundos, podemos concluir facilmente que as duas consultas não têm nenhuma diferença de desempenho exibida pelo SQL Server Engine.
Nota : a RAM atinge quase 100% de uso nas duas execuções. Eu reiniciei o serviço SQL Server antes de iniciar as duas execuções.
fonte
Eu executei isso centenas de vezes, limpando o cache todas as vezes. Os resultados variam de tempos em tempos, conforme a carga do servidor varia, mas quase sempre
count(*)
apresenta um tempo de CPU mais alto.fonte
count(*)
ecount(1)
retornar resultados a alguns ms um do outro, mesmo ao contar uma tabela com 4,5 milhões de linhas, na minha instância do SQL 2008.Há um artigo mostrando que a
COUNT(1)
sobre a Oracle é apenas um alias paraCOUNT(*)
, com uma prova sobre isso.Vou citar algumas partes:
Com um usuário com
ALTER SESSION
privilégios, você pode colocar umtracefile_identifier
, habilitar o rastreamento otimizador e executar oCOUNT(1)
select, como:SELECT /* test-1 */ COUNT(1) FROM employees;
.Depois disso, você precisa localizar os arquivos de rastreamento, o que pode ser feito
SELECT VALUE FROM V$DIAG_INFO WHERE NAME = 'Diag Trace';
. Posteriormente no arquivo, você encontrará:Como você pode ver, é apenas um apelido para
COUNT(*)
.Outro comentário importante:
COUNT(*)
foi realmente mais rápido, há duas décadas, no Oracle, antes do Oracle 7.3:Para outros bancos de dados como o Sql Server, ele deve ser pesquisado individualmente para cada um.
Eu sei que esta pergunta é específica para o Sql Server, mas as outras perguntas sobre SO sobre o mesmo assunto, sem mencionar o banco de dados, foram fechadas e marcadas como duplicadas nesta resposta.
fonte
Em todos os RDBMS, as duas maneiras de contar são equivalentes em termos de qual resultado elas produzem. Em relação ao desempenho, não observei nenhuma diferença de desempenho no SQL Server, mas pode valer a pena ressaltar que alguns RDBMS, por exemplo
COUNT(1)
, PostgreSQL 11, têm implementações menos ideais , pois verificam a nulidade da expressão de argumento, como pode ser visto nesta publicação .Encontrei uma diferença de desempenho de 10% para 1 milhão de linhas ao executar:
fonte
COUNT (1) não é substancialmente diferente de COUNT (*), se houver. Quanto à questão de COUNTing NULLable COLUMNs, isso pode ser simples para demonstrar as diferenças entre COUNT (*) e COUNT (<some col>) -
fonte