2011-02-10 33 views
7
UPDATE table1 
     SET col1 = 'Y' 
    WHERE col2 in (select col2 from table2) 

En la consulta anterior, imagine que la consulta interna devuelve 10000 filas. ¿Esta consulta con la cláusula IN afecta el rendimiento?¿Cómo afecta la cláusula IN el rendimiento en Oracle?

En caso afirmativo, ¿qué se puede hacer para una ejecución más rápida?

+0

Si el sub-consulta devuelve 10000 resultados el tiempo de ejecución será igual a cero, ya que genera un error. Supongo que quieres escribir IN en lugar de = para la subselección? –

+0

Lo tienes. He hecho el cambio, gracias. – Vivek

+1

si la respuesta proporcionada por @zerkms fue útil para usted, acéptela. Consulte las preguntas frecuentes para saber por qué debería hacer esto. :-) –

Respuesta

3
UPDATE table1 outer 
    SET col1 = 'Y' 
WHERE EXISTS (select null 
       from table2 
       WHERE col2 = outer.col2) 

Esto podría ser mejor

Para conseguir la idea que es mejor - mira el plan de ejecución.

+2

Pensé que se trataba de un problema resuelto porque para el optimizador de Oracle no suele haber diferencia entre IN y EXISTS y uno se convertirá al otro según corresponda. http://blogs.oracle.com/optimizer/2010/09/optimizer_transformations_subquery_unesting_part_1.html –

11

si la subconsulta devuelve un gran número de filas en comparación con el número de filas en la Tabla 1, el optimizador es probable que producir un plan como este:

-------------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time 
-------------------------------------------------------------------------------- 
| 0 | UPDATE STATEMENT |  | 300K| 24M|  | 1581 (1)| 00:0 
| 1 | UPDATE    | TABLE1 |  |  |  |   | 
|* 2 | HASH JOIN SEMI |  | 300K| 24M| 9384K| 1581 (1)| 00:0 
| 3 | TABLE ACCESS FULL| TABLE1 | 300K| 5860K|  | 355 (2)| 00:0 
| 4 | TABLE ACCESS FULL| TABLE2 | 168K| 10M|  | 144 (2)| 00:0 
-------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
--------------------------------------------------- 
    2 - access("COL2"="COL2") 

Se explorará ambas tablas una vez y actualizar sólo las filas en la TABLA 1 común a ambas tablas. Este es un plan altamente eficiente si necesita actualizar muchas filas.

A veces, la consulta interna tendrá pocas filas en comparación con el número de filas en la TABLA1. Si usted tiene un índice en TABLE1(col2), entonces podría obtener un plan similar a éste:

------------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------- 
| 0 | UPDATE STATEMENT  |  | 93 | 4557 | 247 (1)| 00:00:03 | 
| 1 | UPDATE    | TABLE1 |  |  |   |   | 
| 2 | NESTED LOOPS  |  | 93 | 4557 | 247 (1)| 00:00:03 | 
| 3 | SORT UNIQUE  |  | 51 | 1326 | 142 (0)| 00:00:02 | 
| 4 |  TABLE ACCESS FULL| TABLE2 | 51 | 1326 | 142 (0)| 00:00:02 | 
|* 5 | INDEX RANGE SCAN | IDX1 |  2 | 46 |  2 (0)| 00:00:01 | 
------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
--------------------------------------------------- 
    5 - access("T1"."COL2"="T2"."COL2") 

En ese caso, Oracle va a leer las filas de TABLA2 y para cada fila (única), lleve a cabo un acceso índice en Table1 .

¿Qué acceso es más rápido depende de la selectividad de la consulta interna y la agrupación del índice en TABLE1 (son las filas con valor similar de col2 en TABLE1 uno al lado del otro o al azar?). En cualquier caso, en cuanto al rendimiento, si necesita realizar esta actualización, esta consulta es una de las formas más rápidas de hacerlo.

+0

¿Qué ocurre con mi consulta?;-) Agregue un plan de ejecución para uno con 'EXISTS' – zerkms

+3

@zerkms: lo siento, olvidé mencionar que el optimizador transforma las subconsultas IN en las subconsultas EXIST equivalentes. Por lo tanto, producen el mismo plan. Personalmente encuentro declaraciones IN más legibles, pero esto es muy subjetivo :) –

+0

no lo sabía, gracias. – zerkms

2

De Oracle:

11.5.3.4 El uso de EXISTE EN frente a subconsultas

En ciertas circunstancias, es mejor para su uso en lugar de existir. En en general, si el predicado selectivo es en la subconsulta, entonces use IN. Si el predicado selectivo se encuentra en la consulta principal , utilice EXISTS.

Desde mi experiencia, he visto mejores planes utilizando EXISTS donde la subconsulta devuelve una gran cantidad de filas.

Ver here para más discusión de Oracle

Cuestiones relacionadas