Meu primeiro palpite seria que OU tenha um desempenho melhor, a menos que o mecanismo SQL converta IN em OU nos bastidores. Você já viu o plano de consulta desses dois?
Suponho que você queira saber a diferença de desempenho entre os seguintes:
WHERE foo IN('a','b','c')WHERE foo ='a'OR foo ='b'OR foo ='c'
De acordo com o manual do MySQL, se os valores são constantes, INclassifica a lista e, em seguida, usa uma pesquisa binária. Eu imagino que os ORavalie um por um em nenhuma ordem particular. Então, INé mais rápido em algumas circunstâncias.
A melhor maneira de saber é criar um perfil tanto no seu banco de dados com dados específicos para ver qual é mais rápido.
Eu tentei ambos em um MySQL com 1000000 linhas. Quando a coluna é indexada, não há diferença perceptível no desempenho - ambas são quase instantâneas. Quando a coluna não está indexada, obtive estes resultados:
SELECT COUNT(*)FROM t_inner WHERE val IN(1000,2000,3000,4000,5000,6000,7000,8000,9000);1row fetched in0.0032(1.2679 seconds)SELECT COUNT(*)FROM t_inner WHERE val =1000OR val =2000OR val =3000OR val =4000OR val =5000OR val =6000OR val =7000OR val =8000OR val =9000;1row fetched in0.0026(1.7385 seconds)
Portanto, neste caso, o método usando OR é cerca de 30% mais lento. Adicionar mais termos aumenta a diferença. Os resultados podem variar em outros bancos de dados e em outros dados.
Se o otimizador vale seu sal, ele deve executar o mesmo.
Janick Bernet
27
@inflagranti: Infelizmente, nenhum otimizador é perfeito. Otimizadores são programas extremamente complexos e cada implementação terá seus próprios pontos fortes e fracos. É por isso que digo que você deve criar um perfil em uma implementação específica. Eu imagino que a estrutura extra do INmétodo facilite a otimização do que várias ORcláusulas possivelmente relacionadas . Eu ficaria surpreso se houver um mecanismo em que o ORmétodo seja mais rápido, mas não estou surpreso que haja momentos em que OU seja mais lento.
Mark Byers
2
@ MarkByers O otimizador não poderia sempre substituir vários ORs por um IN?
precisa saber é
36
A melhor maneira de descobrir é examinar o plano de execução.
Eu tentei com o Oracle e era exatamente o mesmo.
CREATETABLE performance_test AS(SELECT*FROM dba_objects );SELECT*FROM performance_test
WHERE object_name IN('DBMS_STANDARD','DBMS_REGISTRY','DBMS_LOB');
Mesmo que a consulta use IN, o Plano de Execução diz que usa OR:
-------------------------------------------------------------------------------------- | Id | Operation | Name |Rows| Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------------- |0|SELECT STATEMENT ||8|1416|163(2)|00:00:02||*1|TABLE ACCESS FULL| PERFORMANCE_TEST |8|1416|163(2)|00:00:02|--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):--------------------------------------------------- 1- filter("OBJECT_NAME"='DBMS_LOB'OR"OBJECT_NAME"='DBMS_REGISTRY'OR"OBJECT_NAME"='DBMS_STANDARD')
O que acontece no Oracle se você tiver mais de 3 valores que está testando? Você sabe se o Oracle não consegue executar a mesma otimização de pesquisa binária que o MySQL ou executa nos dois casos?
Mark Byers
2
@ Mark Byers: Eu tentei a mesma consulta com 10 valores, ainda o mesmo resultado. Observe que o otimizador utilizou meus valores em ordem alfabética. Eu não ficaria surpreso se a Oracle fez alguma otimização interna desse filtro ...
Peter Lang
5
A Oracle também possui uma INLIST ITERATORoperação, que selecionaria se houvesse um índice que pudesse usar. Ainda assim, quando eu tentei sair, tanto INe ORacabam com o mesmo plano de execução.
Cheran Shunmugavel
7
O operador OR precisa de um processo de avaliação muito mais complexo que o construto IN, pois permite muitas condições, não apenas iguais a IN.
Aqui está um exemplo do que você pode usar com OU, mas que não é compatível com IN: maior. maior ou igual, menor, menor ou igual, LIKE e mais parecido com o oracle REGEXP_LIKE. Além disso, considere que as condições nem sempre podem comparar o mesmo valor.
Para o otimizador de consultas, é mais fácil gerenciar o operador IN porque é apenas uma construção que define o operador OR em várias condições com o operador = no mesmo valor. Se você usar o operador OR, o otimizador poderá não considerar que você está sempre usando o operador = no mesmo valor e, se ele não executar uma elaboração mais profunda e muito mais complexa, provavelmente poderá excluir que possa haver apenas = operadores para os mesmos valores em todas as condições envolvidas, com uma conseqüente exclusão de métodos de pesquisa otimizados, como a pesquisa binária já mencionada.
[EDIT] Provavelmente, um otimizador pode não implementar o processo de avaliação IN otimizado, mas isso não exclui que uma vez isso poderia acontecer (com uma atualização da versão do banco de dados). Portanto, se você usar o operador OR, a elaboração otimizada não será usada no seu caso.
Eu acho que o oracle é inteligente o suficiente para converter o menos eficiente (o que for) para o outro. Então eu acho que a resposta deve depender da legibilidade de cada um (onde eu acho que INclaramente vence)
ORfaz sentido (do ponto de vista da legibilidade), quando há menos valores a serem comparados.
INé útil esp. quando você tem uma fonte dinâmica, com a qual deseja comparar valores.
Outra alternativa é usar a JOINcom uma tabela temporária.
Não acho que o desempenho deva ser um problema, desde que você tenha os índices necessários.
Respostas:
Suponho que você queira saber a diferença de desempenho entre os seguintes:
De acordo com o manual do MySQL, se os valores são constantes,
IN
classifica a lista e, em seguida, usa uma pesquisa binária. Eu imagino que osOR
avalie um por um em nenhuma ordem particular. Então,IN
é mais rápido em algumas circunstâncias.A melhor maneira de saber é criar um perfil tanto no seu banco de dados com dados específicos para ver qual é mais rápido.
Eu tentei ambos em um MySQL com 1000000 linhas. Quando a coluna é indexada, não há diferença perceptível no desempenho - ambas são quase instantâneas. Quando a coluna não está indexada, obtive estes resultados:
Portanto, neste caso, o método usando OR é cerca de 30% mais lento. Adicionar mais termos aumenta a diferença. Os resultados podem variar em outros bancos de dados e em outros dados.
fonte
IN
método facilite a otimização do que váriasOR
cláusulas possivelmente relacionadas . Eu ficaria surpreso se houver um mecanismo em que oOR
método seja mais rápido, mas não estou surpreso que haja momentos em que OU seja mais lento.OR
s por umIN
?A melhor maneira de descobrir é examinar o plano de execução.
Eu tentei com o Oracle e era exatamente o mesmo.
Mesmo que a consulta use
IN
, o Plano de Execução diz que usaOR
:fonte
INLIST ITERATOR
operação, que selecionaria se houvesse um índice que pudesse usar. Ainda assim, quando eu tentei sair, tantoIN
eOR
acabam com o mesmo plano de execução.O operador OR precisa de um processo de avaliação muito mais complexo que o construto IN, pois permite muitas condições, não apenas iguais a IN.
Aqui está um exemplo do que você pode usar com OU, mas que não é compatível com IN: maior. maior ou igual, menor, menor ou igual, LIKE e mais parecido com o oracle REGEXP_LIKE. Além disso, considere que as condições nem sempre podem comparar o mesmo valor.
Para o otimizador de consultas, é mais fácil gerenciar o operador IN porque é apenas uma construção que define o operador OR em várias condições com o operador = no mesmo valor. Se você usar o operador OR, o otimizador poderá não considerar que você está sempre usando o operador = no mesmo valor e, se ele não executar uma elaboração mais profunda e muito mais complexa, provavelmente poderá excluir que possa haver apenas = operadores para os mesmos valores em todas as condições envolvidas, com uma conseqüente exclusão de métodos de pesquisa otimizados, como a pesquisa binária já mencionada.
[EDIT] Provavelmente, um otimizador pode não implementar o processo de avaliação IN otimizado, mas isso não exclui que uma vez isso poderia acontecer (com uma atualização da versão do banco de dados). Portanto, se você usar o operador OR, a elaboração otimizada não será usada no seu caso.
fonte
Eu acho que o oracle é inteligente o suficiente para converter o menos eficiente (o que for) para o outro. Então eu acho que a resposta deve depender da legibilidade de cada um (onde eu acho que
IN
claramente vence)fonte
OR
faz sentido (do ponto de vista da legibilidade), quando há menos valores a serem comparados.IN
é útil esp. quando você tem uma fonte dinâmica, com a qual deseja comparar valores.Outra alternativa é usar a
JOIN
com uma tabela temporária.Não acho que o desempenho deva ser um problema, desde que você tenha os índices necessários.
fonte
Eu fiz uma consulta SQL em um grande número de OR (350). O Postgres faz isso 437.80ms .
Agora use IN:
23.18ms
fonte