In vs. Exists
Antes de desglosar la ejecución de IN y EXISTS para una su optimización, menciono la forma de implementarse.
IN
SELECT campo1, campo2, …, campoN
FROM tabla1
WHERE campoX IN (–subconsulta
SELECT campo1
FROM tabla2
WHERE condicion);
Cierto.
Esta consulta podría implementarse como una natural join. Se trata de un ejemplo. Oracle en ambos casos, tratándose de subconsultas simples, las interpreta como joins y resuelven el mismo plan de ejecución.
SELECT t1.campo1, t1.campo2, …, t1.campoN
FROM tabla1 t1, tabla2 t2
WHERE t1.campoX = t2.campo1
AND condicion;
Es decir, ambas consultas combinan los resultados de Tabla1 y Tabla2, unidos por las columnas t1.campoX y t2.campo1 de modo que visualicen únicamente los resultados de la tabla1 que cumplen la condición de combinación.
La interpretación de la consulta, realizada con IN, es la siguiente:
Selecciona el campo1, campo2, … hasta campoN
de la tabla tabla1
unicamente para las filas cuyo campoX se encuentre en la siguiente lista de valores campo1 de la tabla2, que cumplan con la condición condicion.
La forma de resolver esta petición, para el servidor, es consultar la tabla2 en la subconsulta y delimitar después qué campos de la tabla1 cumplen la condición de join.
EXISTS
SELECT campo1, campo2, …, campoN
FROM tabla1
WHERE EXISTS (–subconsulta
SELECT NULL
FROM tabla2
WHERE t1.campoX=t2.campo1
AND condicion);
No existe en esta forma una comparación de campos, salvo en la subconsulta. Ésta devuelve NULL (ni siquiera tendría que devolver un valor concreto para ser válida) y su interpretación semántica es la siguiente:
Selecciona el campo1, campo2, … hasta campoN
de la tabla tabla1
unicamente cuando la subconsulta devuelva un registro (aunque éste sea NULL).
La subconsulta, por tanto, devolverá un registro para aquellos elementos de la tabla2 cuyo campo1 sea igual que el campoX de la tabla principal.
Por lo que Oracle entiende que la consulta más idónea a resolverse antes es la principal, resolver los valores de campoX, y posteriormente compararlos con tabla2.
Es decir, en la ejecución con EXISTS, Oracle entiende que la consulta principal debe resolverse primero, y la subconsulta después. Justo al contrario que IN, lo que puede producir diferentes planes de ejecución.
Generalmente, IN resulta más ventajoso cuando la ejecución de la subconsulta tiene poco coste respecto a la principal, y EXISTS cuando sucede al revés.
(…continuará…)