Mi primera suposición sería que OR funciona mejor, a menos que el motor SQL convierta IN en OR detrás de escena. ¿Has visto el plan de consulta de estos dos?
Supongo que quiere saber la diferencia de rendimiento entre los siguientes:
WHERE foo IN('a','b','c')WHERE foo ='a'OR foo ='b'OR foo ='c'
Según el manual de MySQL, si los valores son constantes, INordena la lista y luego utiliza una búsqueda binaria. Me imagino que los ORevalúa uno por uno sin ningún orden en particular. Entonces INes más rápido en algunas circunstancias.
La mejor manera de saber es perfilar ambos en su base de datos con sus datos específicos para ver cuál es más rápido.
Probé ambos en un MySQL con 1000000 filas. Cuando se indexa la columna, no hay una diferencia apreciable en el rendimiento: ambos son casi instantáneos. Cuando la columna no está indexada obtuve estos 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)
Entonces, en este caso, el método que usa OR es aproximadamente un 30% más lento. Agregar más términos aumenta la diferencia. Los resultados pueden variar en otras bases de datos y en otros datos.
Si el optimizador vale la pena, deben realizar lo mismo.
Janick Bernet
27
@inflagranti: Desafortunadamente, ningún optimizador es perfecto. Los optimizadores son programas extremadamente complejos y cada implementación tendrá sus propias fortalezas y debilidades. Es por eso que digo que debe perfilar una implementación específica. Me imagino que la estructura adicional del INmétodo hace que sea más fácil de optimizar que un montón de ORcláusulas posiblemente relacionadas . Me sorprendería si hay un motor donde el ORmétodo es más rápido, pero no me sorprende que haya momentos en que OR sea más lento.
Mark Byers
2
@MarkByers ¿No podría el optimizador siempre sustituir múltiples ORs con un IN?
tymtam
36
La mejor manera de averiguarlo es mirando el Plan de ejecución.
¿Qué sucede en Oracle si tiene más de 3 valores que está probando? ¿Sabe si Oracle no puede realizar la misma optimización de búsqueda binaria que MySQL o lo hace en ambos casos?
Mark Byers
2
@ Mark Byers: Intenté la misma consulta con 10 valores, todavía el mismo resultado. Tenga en cuenta que el optimizador recurrió a mis valores en orden alfabético. No me sorprendería si Oracle hiciera alguna optimización interna de ese filtro ...
Peter Lang
55
Oracle también tiene una INLIST ITERATORoperación, que seleccionaría si hubiera un índice que pudiera usar. Aún así, cuando lo probé, tanto INy ORterminar con el mismo plan de ejecución.
Cheran Shunmugavel
7
El operador OR necesita un proceso de evaluación mucho más complejo que la construcción IN porque permite muchas condiciones, no solo iguales a IN.
Aquí hay un ejemplo de lo que puede usar con OR pero que no es compatible con IN: mayor. mayor o igual, menor, menor o igual, ME GUSTA y algunos más como el oráculo REGEXP_LIKE. Además, considere que las condiciones no siempre pueden comparar el mismo valor.
Para el optimizador de consultas, es más fácil administrar el operador IN porque es solo una construcción que define el operador OR en múltiples condiciones con = operador en el mismo valor. Si usa el operador OR, el optimizador puede no considerar que siempre está usando el operador = en el mismo valor y, si no realiza una elaboración más profunda y mucho más compleja, probablemente podría excluir que solo haya = operadores para los mismos valores en todas las condiciones involucradas, con la consiguiente exclusión de métodos de búsqueda optimizados como la búsqueda binaria ya mencionada.
[EDITAR] Probablemente un optimizador puede no implementar el proceso de evaluación IN optimizado, pero esto no excluye que una vez podría suceder (con una actualización de la versión de la base de datos). Entonces, si usa el operador OR, esa elaboración optimizada no se usará en su caso.
Creo que Oracle es lo suficientemente inteligente como para convertir el menos eficiente (lo que sea) en el otro. Así que creo que la respuesta debería depender de la legibilidad de cada uno (donde creo que INclaramente gana)
ORtiene sentido (desde el punto de vista de la legibilidad), cuando hay menos valores para comparar.
INes útil especialmente cuando tiene una fuente dinámica, con la que desea comparar los valores.
Otra alternativa es usar a JOINcon una tabla temporal.
No creo que el rendimiento deba ser un problema, siempre que tenga los índices necesarios.
Respuestas:
Supongo que quiere saber la diferencia de rendimiento entre los siguientes:
Según el manual de MySQL, si los valores son constantes,
IN
ordena la lista y luego utiliza una búsqueda binaria. Me imagino que losOR
evalúa uno por uno sin ningún orden en particular. EntoncesIN
es más rápido en algunas circunstancias.La mejor manera de saber es perfilar ambos en su base de datos con sus datos específicos para ver cuál es más rápido.
Probé ambos en un MySQL con 1000000 filas. Cuando se indexa la columna, no hay una diferencia apreciable en el rendimiento: ambos son casi instantáneos. Cuando la columna no está indexada obtuve estos resultados:
Entonces, en este caso, el método que usa OR es aproximadamente un 30% más lento. Agregar más términos aumenta la diferencia. Los resultados pueden variar en otras bases de datos y en otros datos.
fuente
IN
método hace que sea más fácil de optimizar que un montón deOR
cláusulas posiblemente relacionadas . Me sorprendería si hay un motor donde elOR
método es más rápido, pero no me sorprende que haya momentos en que OR sea más lento.OR
s con unIN
?La mejor manera de averiguarlo es mirando el Plan de ejecución.
Lo probé con Oracle , y fue exactamente lo mismo.
Aunque la consulta usa
IN
, el Plan de ejecución dice que usaOR
:fuente
INLIST ITERATOR
operación, que seleccionaría si hubiera un índice que pudiera usar. Aún así, cuando lo probé, tantoIN
yOR
terminar con el mismo plan de ejecución.El operador OR necesita un proceso de evaluación mucho más complejo que la construcción IN porque permite muchas condiciones, no solo iguales a IN.
Aquí hay un ejemplo de lo que puede usar con OR pero que no es compatible con IN: mayor. mayor o igual, menor, menor o igual, ME GUSTA y algunos más como el oráculo REGEXP_LIKE. Además, considere que las condiciones no siempre pueden comparar el mismo valor.
Para el optimizador de consultas, es más fácil administrar el operador IN porque es solo una construcción que define el operador OR en múltiples condiciones con = operador en el mismo valor. Si usa el operador OR, el optimizador puede no considerar que siempre está usando el operador = en el mismo valor y, si no realiza una elaboración más profunda y mucho más compleja, probablemente podría excluir que solo haya = operadores para los mismos valores en todas las condiciones involucradas, con la consiguiente exclusión de métodos de búsqueda optimizados como la búsqueda binaria ya mencionada.
[EDITAR] Probablemente un optimizador puede no implementar el proceso de evaluación IN optimizado, pero esto no excluye que una vez podría suceder (con una actualización de la versión de la base de datos). Entonces, si usa el operador OR, esa elaboración optimizada no se usará en su caso.
fuente
Creo que Oracle es lo suficientemente inteligente como para convertir el menos eficiente (lo que sea) en el otro. Así que creo que la respuesta debería depender de la legibilidad de cada uno (donde creo que
IN
claramente gana)fuente
OR
tiene sentido (desde el punto de vista de la legibilidad), cuando hay menos valores para comparar.IN
es útil especialmente cuando tiene una fuente dinámica, con la que desea comparar los valores.Otra alternativa es usar a
JOIN
con una tabla temporal.No creo que el rendimiento deba ser un problema, siempre que tenga los índices necesarios.
fuente
Hice una consulta SQL en una gran cantidad de OR (350). Postgres lo hace 437.80ms .
Ahora usa IN:
23,18 ms
fuente