Cuando se trata de grandes bases de datos, ¿cuál funciona mejor, IN
o OR
en la Where
cláusula SQL ?
¿Hay alguna diferencia en la forma en que se ejecutan?
Cuando se trata de grandes bases de datos, ¿cuál funciona mejor, IN
o OR
en la Where
cláusula SQL ?
¿Hay alguna diferencia en la forma en que se ejecutan?
Respuestas:
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, IN
ordena la lista y luego utiliza una búsqueda binaria. Me imagino que los OR
evalúa uno por uno sin ningún orden en particular. Entonces IN
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:
SELECT COUNT(*) FROM t_inner WHERE val IN (1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);
1 row fetched in 0.0032 (1.2679 seconds)
SELECT COUNT(*) FROM t_inner WHERE val = 1000 OR val = 2000 OR val = 3000 OR val = 4000 OR val = 5000 OR val = 6000 OR val = 7000 OR val = 8000 OR val = 9000;
1 row fetched in 0.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.
IN
método hace que sea más fácil de optimizar que un montón de OR
cláusulas posiblemente relacionadas . Me sorprendería si hay un motor donde el OR
método es más rápido, pero no me sorprende que haya momentos en que OR sea más lento.
OR
s con un IN
?
La mejor manera de averiguarlo es mirando el Plan de ejecución.
Lo probé con Oracle , y fue exactamente lo mismo.
CREATE TABLE performance_test AS ( SELECT * FROM dba_objects );
SELECT * FROM performance_test
WHERE object_name IN ('DBMS_STANDARD', 'DBMS_REGISTRY', 'DBMS_LOB' );
Aunque la consulta usa IN
, el Plan de ejecución dice 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')
INLIST ITERATOR
operación, que seleccionaría si hubiera un índice que pudiera usar. Aún así, cuando lo probé, tanto IN
y OR
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.
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.
Hice una consulta SQL en una gran cantidad de OR (350). Postgres lo hace 437.80ms .
Ahora usa IN:
23,18 ms