Optimización SQL en Oracle

In vs. Exists

2005-09-30 · Blog

He escrito anteriormente en este artículo sobre el uso de NOT IN y NOT EXISTS, mencionando que se trataba de cláusulas diferentes y que, por lo tanto, podían generar diferentes resultados. También mencioné que en su forma natural, IN y EXISTS suponen semánticamente operaciones distintas con diferentes vías de ejecución la mayoría de los casos, pero que pueden implementarse de forma que los resultados sean idénticos y permitir así el sustituir IN por EXISTS y viceversa.

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á…)

← Volver al blog