Qual forma de contar várias linhas deve ser mais rápida no MySQL?
Este:
SELECT COUNT(*) FROM ... WHERE ...
Ou a alternativa:
SELECT 1 FROM ... WHERE ...
// and then count the results with a built-in function, e.g. in PHP mysql_num_rows()
Alguém poderia pensar que o primeiro método deveria ser mais rápido, já que este é claramente o território do banco de dados e o mecanismo de banco de dados deveria ser mais rápido do que qualquer outra pessoa ao determinar coisas como essa internamente.
mysql
performance
Franz
fonte
fonte
SELECT 1
e nãoSELECT *
. Existe alguma diferença?mysql_query()
, por exemplo, todo o conjunto de resultados é enviado ao PHP a partir do MySQL, independentemente do que você fazer com esses dados.Respostas:
Quando você
COUNT(*)
leva em índices de coluna de contagem, então será o melhor resultado. Mysql com mecanismo MyISAM realmente armazena contagem de linhas, ele não conta todas as linhas cada vez que você tenta contar todas as linhas. (com base na coluna da chave primária)Usar o PHP para contar linhas não é muito inteligente, porque você tem que enviar dados do mysql para o php. Por que fazer isso quando você pode conseguir o mesmo no lado do mysql?
Se o
COUNT(*)
for lento, você deve executarEXPLAIN
a consulta e verificar se os índices são realmente usados e onde devem ser adicionados.O seguinte não é o caminho mais rápido , mas há um caso em
COUNT(*)
que realmente não se encaixa - quando você começa a agrupar os resultados, pode ter problemas, ondeCOUNT
realmente não conta todas as linhas.A solução é
SQL_CALC_FOUND_ROWS
. Isso geralmente é usado quando você está selecionando linhas, mas ainda precisa saber a contagem total de linhas (por exemplo, para paginação). Ao selecionar linhas de dados, basta anexar aSQL_CALC_FOUND_ROWS
palavra - chave após SELECT:Depois de selecionar as linhas necessárias, você pode obter a contagem com esta única consulta:
FOUND_ROWS()
deve ser chamado imediatamente após a consulta de seleção de dados.Em conclusão, tudo se resume a quantas entradas você tem e o que está na instrução WHERE. Você realmente deve prestar atenção em como os índices estão sendo usados, quando há muitas linhas (dezenas de milhares, milhões e mais).
fonte
MyISAM
armazena a contagem de linhas. Outros mecanismos de armazenamentoInnoDB
não armazenam contagens de linhas e contam todas as linhas a cada vez .SELECT 1 FROM ... LIMIT 1
ouSELECT COUNT(*) FROM ...
?WHERE
cláusula.SELECT COUNT(*) FROM ...
pode levar um tempo considerável, dependendo do que precisa ser verificado (por exemplo, uma tabela muito grande ou índice de milhões / bilhões / trilhões de linhas).SELECT 1 FROM ... LIMIT 1
retorna imediatamente porque você o está limitando à primeira linha.Depois de falar com meus companheiros de equipe, Ricardo nos disse que a maneira mais rápida é:
Mas é preciso lembrar que o resultado pode não ser exato.
Você também pode usá-lo na linha de comando:
Mais informações: http://dev.mysql.com/doc/refman/5.7/en/show-table-status.html
E você pode encontrar uma discussão completa em mysqlperformanceblog
fonte
SHOW TABLE STATUS
(ou equivalenteSELECT
eminformation_schema
) é rápido, mas não lida com umaWHERE
cláusula. É preciso para MyISAM, mas impreciso (às vezes errado por um fator de 2) para InnoDB.Ótima pergunta, ótimas respostas. Esta é uma maneira rápida de repetir os resultados se alguém estiver lendo esta página e perder aquela parte:
fonte
as count
?id
é confuso à primeira vista.Esta consulta (que é semelhante ao que bayuah postou ) mostra um bom resumo de todas as contagens de tabelas dentro de um banco de dados: (versão simplificada do procedimento armazenado por Ivan Cachicatari que eu recomendo fortemente).
Exemplo:
fonte
information_schema
não é o mesmo que aquele retornado porSELECT count(*) FROM
caso o InnoDB seja usado. Se você precisa de um valor estrito, tenha em mente que este método fornece um valor estrito somente com tabelas MyISAM. Com InnoDB, o número de linhas é uma aproximação aproximada.Sempre entendi que o que segue me dará os tempos de resposta mais rápidos.
fonte
SELECT 1 ...
retornará quantas linhasWHERE
eLIMIT
solicitar, e todas serão "1".show table status like '<TABLE NAME>'
Isso será muito mais rápido.WHERE
cláusula. E, para InnoDB, é apenas uma estimativa.Se você precisar obter a contagem de todo o conjunto de resultados, poderá seguir a seguinte abordagem:
Normalmente, isso não é mais rápido do que usar,
COUNT
embora se possa pensar o contrário, porque está fazendo o cálculo internamente e não envia os dados de volta ao usuário, portanto, suspeita-se de uma melhoria de desempenho.Fazer essas duas consultas é bom para paginação para obter totais, mas não particularmente para usar
WHERE
cláusulas.fonte
Fiz alguns benchmarks para comparar o tempo de execução de
COUNT(*)
vsCOUNT(id)
(id é a chave primária da tabela - indexada).Número de testes: 10 * 1000 consultas
Resultados:
COUNT(*)
é mais rápido 7%VER GRÁFICO: benchmarkgraph
Meu conselho é usar:
SELECT COUNT(*) FROM table
fonte
COUNT(1)
, seria interessante ver alguns benchmarks lá ...Experimente isto:
fonte
select count(*) from table_name
ou algo mais. dba.stackexchange.com/questions/151769/…Talvez você queira considerar fazer a
SELECT max(Id) - min(Id) + 1
. Isso só funcionará se seus IDs forem sequenciais e as linhas não forem excluídas. No entanto, é muito rápido.fonte
EXPLAIN SELECT id FROM ....
fez o truque para mim. e pude ver o número de linhas sob arows
coluna do resultado.fonte
Lidei com tabelas para o governo alemão com às vezes 60 milhões de registros.
E precisávamos saber muitas vezes o total de linhas.
Assim, nós, programadores de banco de dados, decidimos que em cada tabela o registro um é sempre o registro no qual o número total de registros está armazenado. Atualizamos esse número, dependendo das linhas INSERT ou DELETE.
Tentamos de todas as outras maneiras. Esta é de longe a maneira mais rápida.
fonte
Uma instrução count (*) com uma condição where na chave primária retornou a contagem de linhas muito mais rápido para mim, evitando a varredura completa da tabela.
Isso foi muito mais rápido para mim do que
fonte