Eu tenho algumas duplicatas em um banco de dados que quero inspecionar. Portanto, o que fiz para ver quais são duplicadas, fiz o seguinte:
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
Dessa forma, vou obter todas as linhas com relevantes_field ocorrendo mais de uma vez. Essa consulta leva milissegundos para executar.
Agora, eu queria inspecionar cada uma das duplicatas, então pensei em selecionar cada linha em alguma tabela com um campo relevante na consulta acima, então fiz o seguinte:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
)
Isso acaba sendo extremamente lento por algum motivo (leva minutos). O que exatamente está acontecendo aqui para torná-lo tão lento? relevantes_campo é indexado.
Eventualmente, tentei criar uma visualização "temp_view" a partir da primeira consulta (SELECT relevant_field FROM some_table GROUP BY relevant_field HAVING COUNT(*) > 1)
e, em seguida, fazer minha segunda consulta como esta:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM temp_view
)
E isso funciona muito bem. O MySQL faz isso em alguns milissegundos.
Algum especialista em SQL aqui que pode explicar o que está acontecendo?
Respostas:
Reescreva a consulta neste
Eu acho que
st2.relevant_field
deve estar no select, porque caso contrário ahaving
cláusula dará um erro, mas não tenho 100% de certezaNunca use
IN
com uma subconsulta; isso é notoriamente lento.Sempre use apenas
IN
com uma lista fixa de valores.Mais dicas
SELECT *
selecione apenas os campos que realmente precisa.relevant_field
para acelerar a junção equitativa.group by
na chave primária.Solução geral para 90% de suas
IN (select
consultasUse este código
fonte
HAVING COUNT(*) > 1
. Geralmente é mais rápido no MySQL.st2.relevant_field
não estáNULL
(já está incluído naON
cláusula), não altera o resultado.afield
que nunca seránull
, entendeu. Obrigadogroup by
é emst1.id
, e não sobrest1.relevant_field
.A subconsulta está sendo executada para cada linha porque é uma consulta correlacionada. Pode-se transformar uma consulta correlacionada em uma consulta não correlacionada selecionando tudo da subconsulta, da seguinte forma:
A consulta final ficaria assim:
fonte
SELECT *
empacotamento é necessário.Subconsultas vs junções
http://www.scribd.com/doc/2546837/New-Subquery-Optimizations-In-MySQL-6
fonte
Tentei sua consulta em um dos meus bancos de dados e também a reescrevi como uma junção a uma subconsulta.
Isso funcionou muito mais rápido, tente!
fonte
Tente isto
fonte
Reformatei sua consulta sql lenta com www.prettysql.net
Ao usar uma tabela na consulta e na subconsulta, você sempre deve usar o alias de ambos, assim:
Isso ajuda?
fonte
Primeiramente, você pode encontrar linhas duplicadas e a contagem de linhas é usada quantas vezes e ordenada por número como este;
depois disso, crie uma tabela e insira o resultado nela.
Por fim, exclua as linhas públicas. Não é o início 0. Exceto o primeiro número de cada grupo, exclua todas as linhas públicas.
fonte
Às vezes, quando os dados aumentam, o mysql WHERE IN pode ser bem lento devido à otimização da consulta. Tente usar STRAIGHT_JOIN para dizer ao mysql para executar a consulta como está, por exemplo
mas cuidado: na maioria dos casos, o otimizador mysql funciona muito bem, então eu recomendaria usá-lo somente quando você tiver esse tipo de problema
fonte
Isso é semelhante ao meu caso, onde eu tenho uma tabela chamada
tabel_buku_besar
. O que eu preciso éProcurando registro que tenha
account_code='101.100'
emtabel_buku_besar
que tenhacompanyarea='20000'
e também tenhaIDR
comocurrency
Preciso obter todos os registros dos
tabel_buku_besar
quais possuem account_code igual ao passo 1, mastransaction_number
no resultado do passo 1durante o uso
select ... from...where....transaction_number in (select transaction_number from ....)
, minha consulta é extremamente lenta e às vezes causa o tempo limite da solicitação ou faz com que meu aplicativo não responda ...Eu tento essa combinação e o resultado ... não é ruim ...
fonte
Eu acho que isso é o mais eficiente para descobrir se existe um valor, a lógica pode ser facilmente invertida para descobrir se um valor não existe (isto é, IS NULL);
* Substitua relevantes_campo pelo nome do valor que você deseja verificar existe na sua tabela
* Substitua primaryKey pelo nome da coluna da chave primária na tabela de comparação.
fonte