Eu queria saber se havia uma maneira de obter o número de resultados de uma consulta MySQL e, ao mesmo tempo, limitar os resultados.
A maneira como a paginação funciona (pelo que entendi), primeiro faço algo como
query = SELECT COUNT(*) FROM `table` WHERE `some_condition`
Depois de obter o num_rows (consulta), tenho o número de resultados. Mas, para realmente limitar meus resultados, tenho que fazer uma segunda consulta como:
query2 = SELECT COUNT(*) FROM `table` WHERE `some_condition` LIMIT 0, 10
Minha pergunta: Existe alguma maneira de recuperar o número total de resultados que seriam fornecidos E limitar os resultados retornados em uma única consulta? Ou qualquer forma mais eficiente de fazer isso. Obrigado!
mysql
pagination
double
atp
fonte
fonte
Respostas:
Não, é assim que muitos aplicativos que desejam paginar precisam fazer isso. É confiável e à prova de balas, embora faça a consulta duas vezes. Mas você pode armazenar a contagem em cache por alguns segundos e isso ajudará muito.
A outra maneira é usar a
SQL_CALC_FOUND_ROWS
cláusula e depois chamarSELECT FOUND_ROWS()
. além do fato de você ter que fazer aFOUND_ROWS()
chamada depois, há um problema com isso: há um bug no MySQL que isso afeta asORDER BY
consultas, tornando-as muito mais lentas em tabelas grandes do que a abordagem ingênua de duas consultas.fonte
Quase nunca faço duas consultas.
Basta retornar uma linha a mais do que o necessário, exibir apenas 10 na página e, se houver mais do que exibido, exibir um botão "Avançar".
Sua consulta deve retornar na ordem mais relevante primeiro. Provavelmente, a maioria das pessoas não vai se importar em ir para a página 236 de 412.
Quando você faz uma pesquisa no Google e seus resultados não estão na primeira página, você provavelmente vai para a página dois, não para a nove.
fonte
COUNT
é uma função agregada. Como você retorna a contagem e todos os resultados em uma consulta? A consulta acima retornará apenas 1 linha, não importa como oLIMIT
está definido. Se você adicionarGROUP BY
, ele retornará todos os resultados, masCOUNT
será imprecisoOutra abordagem para evitar a consulta dupla é buscar primeiro todas as linhas da página atual usando uma cláusula LIMIT e, em seguida, fazer uma segunda consulta COUNT (*) se o número máximo de linhas for recuperado.
Em muitas aplicações, o resultado mais provável será que todos os resultados caibam em uma página, e ter que fazer a paginação é a exceção, e não a norma. Nesses casos, a primeira consulta não recuperará o número máximo de resultados.
Por exemplo, as respostas a uma questão stackoverflow raramente passam para uma segunda página. Os comentários sobre uma resposta raramente ultrapassam o limite de 5 ou mais necessários para mostrá-los todos.
Então, nesses aplicativos, você pode simplesmente fazer uma consulta com um LIMIT primeiro e, em seguida, desde que esse limite não seja atingido, você sabe exatamente quantas linhas existem sem a necessidade de fazer uma segunda consulta COUNT (*) - o que deve cobrir a maioria das situações.
fonte
Na maioria das situações, é muito mais rápido e menos intensivo em recursos fazê-lo em duas consultas separadas do que em uma, mesmo que pareça um contra-senso.
Se você usar SQL_CALC_FOUND_ROWS, então para tabelas grandes torna sua consulta muito mais lenta, significativamente mais lenta até do que executar duas consultas, a primeira com COUNT (*) e a segunda com LIMIT. A razão para isso é que SQL_CALC_FOUND_ROWS faz com que a cláusula LIMIT seja aplicada depois de buscar as linhas em vez de antes, portanto, busca a linha inteira para todos os resultados possíveis antes de aplicar os limites. Isso não pode ser satisfeito por um índice porque ele realmente busca os dados.
Se você adotar a abordagem de duas consultas, a primeira apenas buscando COUNT (*) e não realmente buscando dados reais, isso pode ser satisfeito muito mais rapidamente porque geralmente pode usar índices e não precisa buscar os dados reais da linha para cada linha que olha. Então, a segunda consulta só precisa olhar as primeiras linhas $ offset + $ limit e depois retornar.
Esta postagem do blog de desempenho do MySQL explica isso melhor:
http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/
Para obter mais informações sobre como otimizar a paginação, verifique esta postagem e esta postagem .
fonte
Minha resposta pode estar atrasada, mas você pode pular a segunda consulta (com o limite) e apenas filtrar as informações por meio de seu script de back end. Em PHP, por exemplo, você poderia fazer algo como:
Mas é claro que, quando você tem milhares de registros a considerar, isso se torna ineficiente muito rápido. A contagem pré-calculada pode ser uma boa ideia.
Aqui está uma boa leitura sobre o assunto: http://www.percona.com/ppc2009/PPC2009_mysql_pagination.pdf
fonte
fonte
where
cláusula à consulta interna e você obterá o "total" correto junto com os resultados paginados (a página é selecionada com alimit
cláusulaPara quem procura uma resposta em 2020. De acordo com a documentação do MySQL:
"O modificador de consulta SQL_CALC_FOUND_ROWS e a função FOUND_ROWS () que o acompanha estão obsoletos a partir do MySQL 8.0.17 e serão removidos em uma versão futura do MySQL. Como uma substituição, considere executar sua consulta com LIMIT e, em seguida, uma segunda consulta com COUNT (*) e sem LIMIT para determinar se há linhas adicionais. "
Eu acho que isso resolve tudo.
https://dev.mysql.com/doc/refman/8.0/en/information-functions.html#function_found-rows
fonte
Você pode reutilizar a maior parte da consulta em uma subconsulta e defini-la como um identificador. Por exemplo, uma consulta de filme que encontra filmes contendo a ordem das letras por tempo de execução ficaria assim no meu site.
Observe que não sou um especialista em banco de dados e espero que alguém consiga otimizar isso um pouco melhor. Como está, executando-o diretamente da interface de linha de comando SQL, ambos levam cerca de 0,02 segundos no meu laptop.
fonte
fonte