2012-01-17 27 views
14

Tengo una consulta de Oracle que está estructurado como sigue:¿Oracle usa la evaluación de cortocircuito?

SELECT * 
FROM  table 
WHERE X='true' OR 
     Y IN (complicated subquery) 

Si Oracle ve que X es igual a 'verdadero' será todavía tratar de evaluar la (sub consulta) Y EN parte de la cláusula WHERE? Además, en una declaración como esta, ¿la subconsulta se ejecutará varias veces para cada entrada en la tabla? Iba a ser mejor con algo como:

WITH subQ as (complicated subquery) 
SELECT * 
FROM  table 
WHERE X='true' OR 
     Y IN (SELECT id FROM subQ) 

Respuesta

28

Depende. . En general, Oracle no garantiza que una declaración SQL use la evaluación de cortocircuito (aunque PL/SQL está garantizado para realizar una evaluación de cortocircuito). El optimizador de Oracle es libre de evaluar los predicados en el orden que se espera que sea más eficiente. Eso podría significar que el primer predicado se evalúa primero y solo las filas coincidentes tienen el segundo predicado evaluado, pero es completamente posible que ocurra lo contrario o que Oracle transforme la consulta en un tipo de UNION y evalúe ambos predicados antes de combinar los resultados .

Dicho esto, si el optimizador puede determinar en tiempo de compilación que un predicado siempre evaluará a TRUE o FALSE, el optimizador debería tratar eso como una constante. Entonces, si, por ejemplo, hay una restricción en la tabla que impide que X tenga un valor de 'verdadero', el optimizador no debería evaluar el segundo predicado (aunque las diferentes versiones del optimizador tendrán diferentes capacidades para detectar que algo es una constante en el tiempo de compilación).

En cuanto a la segunda parte de su pregunta, sin ver los planes de consulta, es muy difícil de decir. El optimizador de Oracle tiende a ser bastante bueno en la transformación de consultas de una forma a otra si hay formas más eficientes de evaluarlo. Sin embargo, en general, si subQ va a devolver un número relativamente grande de filas en comparación con table, puede ser más eficiente estructurar la consulta como EXISTS que como IN.

+0

Gracias, eso ayuda mucho. – aoi222

+0

"aunque se garantiza que PL/SQL realiza la evaluación de cortocircuito" ¿de dónde toma eso? Intenté esto y consigo un error: 'declare var varchar2 (30); comenzar seleccionar 'cortocircuito' en var desde dual donde 1 = 0 y 1/0 = 0; final; ' –

+5

@IsaacKleinman - Eso sigue siendo SQL. Si pone las condiciones en PL/SQL, verá un cortocircuito. 'begin if (1 <2 o 1/0 = 1) then dbms_output.put_line ('Cortocircuito'); final si; final; ' –

12

Advertencia: Oracle no es mi área de especialización primario.

El optimizador basado en costos debe saber que el costo de X = 'true' es menor que la sub consulta, por lo que es probable que primero evalúe la alternativa más simple. Pero las condiciones AND y OR en SQL son no en cortocircuito como && y || están en C y sus derivados.

La subconsulta puede ser una de dos formas: correlacionada y no correlacionada.

  • Un sub-consulta correlacionada debe ser ejecutada muchas veces (que es por eso que son peligrosos para el rendimiento) porque la correlación significa que el resultado sub-consulta depende de alguna manera en la fila 'que está siendo evaluado actualmente').
  • Una subconsulta no correlacionada solo se ejecutará una vez.

Ejemplo correlacionados sub-consulta:

SELECT * 
    FROM Table1 
WHERE X = 'true' 
    OR Y IN (SELECT Z FROM Table2 WHERE Table2.A = Table1.B) 

Ejemplo no correlacionados sub-consulta:

SELECT * 
    FROM Table1 
WHERE X = 'true' 
    OR Y IN (SELECT Z FROM Table2 WHERE Table2.A > 13) 
+1

Esto también fue muy útil, gracias. – aoi222

1

Independientemente de lo que el optimizador puede o no puede hacer con ANDOR y, si por alguna razón debe cumplir una orden específica de la evaluación, se puede reescribir la consulta, el uso de otras herramientas que se garantiza la evaluación de cortocircuito.

Por ejemplo:

select * from table 1 
where case when X = 'true' then 1 
      when Y in (select ....) then 1 
     end = 1 

Si X es 'verdadero' entonces la expresión caso se evalúa como 1, la segunda "cuando" se omite y la condición se evalúa como TRUE. Si X no es "verdadero", se evalúa la condición IN.

Cuestiones relacionadas