Gostaria de saber se existe alguma diferença em relação ao desempenho entre os seguintes
SELECT ... FROM ... WHERE someFIELD IN(1,2,3,4)
SELECT ... FROM ... WHERE someFIELD between 0 AND 5
SELECT ... FROM ... WHERE someFIELD = 1 OR someFIELD = 2 OR someFIELD = 3 ...
ou o MySQL otimizará o SQL da mesma maneira que os compiladores otimizarão o código?
EDIT: Alterou o AND
's para OR
' s, pelo motivo indicado nos comentários.
mysql
sql
performance
optimization
Scott
fonte
fonte
s I could say that it can also be converted to UNION
que é recomendada para substituir os ORs para otimizar a consulta.Respostas:
Eu precisava saber disso com certeza, então fiz um benchmarking dos dois métodos. Eu sempre achei
IN
muito mais rápido do que usarOR
.Não acredite nas pessoas que dão a sua "opinião", a ciência tem tudo a ver com testes e evidências.
Eu executei um loop de 1000x as consultas equivalentes (por consistência, eu usei
sql_no_cache
):IN
: 2.34969592094sOR
: 5.83781504631sAtualização:
(não tenho o código-fonte do teste original, como era há 6 anos, embora ele retorne um resultado no mesmo intervalo que este teste)
Na solicitação de algum código de amostra para testar isso, este é o caso de uso mais simples possível. Usando o Eloquent para simplificar a sintaxe, o equivalente bruto em SQL executa o mesmo.
fonte
IN
declaração era cerca de 30% mais rápida que umaOR
.Do not believe people who give their "opinion"
Você está 100% certo, Stack Overflow é, infelizmente, cheio delesReturns 1 if expr is equal to any of the values in the IN list, else returns 0. If all values are constants, they are evaluated according to the type of expr and sorted. The search for the item then is done using a binary search. This means
IN is very quick if the IN value list consists entirely of constants
. Otherwise, type conversion takes place according to the rules described at Type Conversion, but applied to all the arguments.
IN
Também fiz um teste para futuros Googlers. A contagem total de resultados retornados é 7264 de 10000
Esta consulta levou
0.1239
segundosEsta consulta levou
0.0433
segundosIN
é 3 vezes mais rápido queOR
fonte
OR
: melhor usar a expressão mais compacta possível.A resposta aceita não explica o motivo.
Abaixo estão citados o MySQL de Alto Desempenho, 3ª Edição.
fonte
Eu acho que o BETWEEN será mais rápido, pois deve ser convertido em:
Entendo que um IN será convertido em várias instruções OR de qualquer maneira. O valor de IN é a facilidade de uso. (Economizando em digitar o nome de cada coluna várias vezes e também facilita o uso com a lógica existente - você não precisa se preocupar com a precedência AND / OR porque a IN é uma instrução. Com várias instruções OR, você tem para garantir que você os coloque entre parênteses para garantir que eles sejam avaliados como uma condição.)
A única resposta real para sua pergunta é PERFIL SUAS PERGUNTAS . Então você saberá o que funciona melhor em sua situação específica.
fonte
Depende do que você está fazendo; quão amplo é o intervalo, qual é o tipo de dados (eu sei que seu exemplo usa um tipo de dados numérico, mas sua pergunta também pode se aplicar a vários tipos de dados diferentes).
Esta é uma instância em que você deseja gravar a consulta nos dois sentidos; faça-o funcionar e use EXPLAIN para descobrir as diferenças de execução.
Tenho certeza de que há uma resposta concreta para isso, mas é assim que, na prática, descobriria a resposta para minha pergunta.
Isso pode ser de alguma ajuda: http://forge.mysql.com/wiki/Top10SQLPerformanceTips
Atenciosamente,
Frank
fonte
Eu acho que uma explicação para a observação do sunseeker é que o MySQL realmente classifica os valores na instrução IN se todos forem valores estáticos e usando a pesquisa binária, que é mais eficiente que a alternativa OR simples. Não me lembro de onde li isso, mas o resultado de sunseeker parece ser uma prova.
fonte
Apenas quando você pensou que era seguro ...
Qual é o seu valor
eq_range_index_dive_limit
? Em particular, você tem mais ou menos itens noIN
cláusula?Isso não incluirá um benchmark, mas examinará um pouco o funcionamento interno. Vamos usar uma ferramenta para ver o que está acontecendo - rastreamento do otimizador.
A pergunta:
SELECT * FROM canada WHERE id ...
Com um
OR
de 3 valores , parte do rastreamento se parece com:...
...
Observe como o ICP está sendo administrado
ORs
. Isso implica queOR
não é transformadoIN
e o InnoDB executará vários=
testes pelo ICP. (Eu não acho que vale a pena considerar o MyISAM.)(Este é o 5.6.22-71.0-log da Percona;
id
é um índice secundário.)Agora para IN () com alguns valores
eq_range_index_dive_limit
= 10; existem 8 valores....
...
Observe que o
IN
arquivo não parece ter sido transformadoOR
.Uma observação lateral: observe que os valores constantes foram classificados . Isso pode ser benéfico de duas maneiras:
Por fim, IN () com muitos valores
...
...
Nota lateral: eu precisava disso devido ao volume do rastreamento:
fonte
OU será mais lento. Se IN ou BETWEEN é mais rápido, dependerá dos seus dados, mas eu espero que BETWEEN seja mais rápido normalmente, pois pode simplesmente variar um intervalo de um índice (assumindo que someField esteja indexado).
fonte
Abaixo estão os detalhes de 6 consultas usando o MySQL 5.6 @SQLFiddle
Em resumo, as 6 consultas cobrem colunas indexadas independentemente e 2 consultas foram usadas por tipo de dados. Todas as consultas resultaram no uso de um índice, independentemente de IN () ou ORs serem usados.
Eu realmente só queria desmascarar as declarações feitas que OR significa que nenhum índice pode ser usado. Isso não é verdade. Os índices podem ser usados em consultas usando OR, conforme as 6 consultas nos exemplos a seguir são exibidas.
Também me parece que muitos ignoraram o fato de que IN () é um atalho de sintaxe para um conjunto de ORs. Em pequena escala, as diferenças de desempenho entre o uso de IN () -v- OR são extremamente (infintessinalmente) marginais.
Embora em escala maior, IN () seja certamente mais conveniente, mas ainda é igual a um conjunto de condições OR logicamente. Alteração de circunstâncias para cada consulta, portanto, sempre é melhor testar sua consulta em suas tabelas.
Resumo dos 6 planos de explicação, todos "Usando a condição de índice" (role para a direita)
SQL Fiddle
Configuração do Esquema do MySQL 5.6 :
.
Consulta 1 :
Resultados :
Consulta 2 :
Resultados :
Consulta 3 :
Resultados :
Consulta 4 :
Resultados :
Consulta 5 :
Resultados :
Consulta 6 :
Resultados :
fonte
Aposto que são iguais, você pode executar um teste fazendo o seguinte:
faça um loop sobre o "in (1,2,3,4)" 500 vezes e veja quanto tempo leva. faça um loop sobre a versão "= 1 ou = 2 ou = 3 ..." 500 vezes e veja quanto tempo é executado.
você também pode tentar uma junção, se someField for um índice e sua tabela for grande, poderá ser mais rápido ...
Eu tentei o método de junção acima no meu SQL Server e é quase o mesmo que o em (1,2,3,4), e ambos resultam em uma busca de índice em cluster. Não tenho certeza de como o MySQL irá lidar com eles.
fonte
2018 : IN (...) é mais rápido. Mas > = && <= é ainda mais rápido que IN .
Aqui está a minha referência .
fonte
Pelo que entendi da maneira como o compilador otimiza esses tipos de consultas, o uso da cláusula IN é mais eficiente do que várias cláusulas OR. Se você tiver valores nos quais a cláusula BETWEEN pode ser usada, isso é ainda mais eficiente.
fonte
Eu sei que, desde que você tenha um índice no Field, o BETWEEN o usará para encontrar rapidamente uma extremidade e depois atravessar para a outra. Isso é mais eficiente.
Cada EXPLAIN que eu vi mostra "IN (...)" e "... OR ..." serem intercambiáveis e igualmente (in) eficientes. O que você esperaria, já que o otimizador não tem como saber se compreende ou não um intervalo. Também é equivalente a um UNION ALL SELECT nos valores individuais.
fonte
Conforme explicado por outros, IN é mais bem escolhido que OU com relação ao desempenho da consulta.
Consultas com condição OR podem levar mais tempo de execução nos casos abaixo.
fonte