2010-04-29 7 views
6

Estoy trabajando con una base de datos de Oracle intentando sintonizar algunas consultas y tengo problemas para entender por qué trabajar una cláusula en particular de una manera particular tiene un impacto tan drástico en el rendimiento de la consulta. He aquí una versión performant de la consulta que estoy haciendo¿Por qué estas consultas aparentemente similares tienen tiempos de ejecución tan drásticamente diferentes?

select * from 
(
    select a.*, rownum rn from 
    ( 
     select * 
     from table_foo 
    ) a where rownum <= 3 
) where rn >= 2 

La misma consulta mediante la sustitución de las dos últimas líneas con este

) a where rownum >=2 rownum <= 3 
) 

realiza horriblemente. Varios órdenes de magnitud peor

) a where rownum between 2 and 3 
) 

también funciona de forma horrible. No entiendo la magia de la primera consulta y cómo aplicarla a otras consultas similares.

+3

Puede ejecutar un análisis de consulta ('EXPLAIN PLAIN', http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/ex_plan.htm) para ver cómo el DBMS ejecuta la consulta. – outis

+0

Como nota al margen, ¿por qué 'seleccionar *' cuando se podía simplemente 'seleccionar * de (seleccionar a. *, Rownum rn de table_foo a donde rownum <= 3) donde rn> = 2'? –

Respuesta

4

Mi entendimiento es que se realice la cesión rownum después (o 'como') se selecciona la fila, por lo que cualquier consulta 'ROWNUM> = n' con n mayor que 1 causará problemas. Lo que se me explicó es que se mira la primera fila; es rownum 1, por lo que no cumple con los criterios y se desecha. La siguiente fila se mira; seguirá siendo rownum 1 ya que el conjunto de resultados está vacío, no cumple los criterios y se descarta. Este proceso continúa hasta que todas las filas hayan sido leídas y rechazadas.

¿La consulta de larga duración realmente produce algún dato? ¿O siempre lo has matado antes de que se completara?

+0

La respuesta será afirmativa: si tiene ROWNUM> = 2 (es decir, cualquier predicado que evalúe como FALSE cuando ROWNUM = 1), la consulta simplemente ejecutará todo el conjunto de datos y no devolverá nada. –

+0

De hecho, lo intenté y sí, la consulta simplemente se ejecutará hasta que se agoten todas las filas y no devuelva nada. Entonces, en esencia, las consultas en cuestión no son idénticas. –

1

ROWNUM es una pseudocolumna (no una columna real) que está disponible en una consulta. A ROWNUM se le asignarán los números 1, 2, 3, 4, ... N, donde N es el número de filas en el conjunto con el que se utiliza ROWNUM. En el primer caso, se están reduciendo el número de filas de la derecha del palo, y en el segundo que tiene que buscar todo para cortar cosas que son más grandes que

2.
Cuestiones relacionadas