2010-04-29 7 views
6

Sto lavorando con un DB Oracle che tenta di sintonizzare alcune query e ho difficoltà a capire perché il funzionamento di una particolare clausola in un modo particolare ha un impatto così drastico sulle prestazioni della query. Ecco una versione performante della query che sto facendoPerché queste query apparentemente simili hanno tempi di esecuzione così drasticamente differenti?

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

La stessa query sostituendo le ultime due righe con questo

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

esegue orribilmente. Diversi ordini di grandezza peggio

) a where rownum between 2 and 3 
) 

esegue anche in modo orribile. Non capisco la magia della prima query e come applicarla a ulteriori query simili.

+3

È possibile eseguire un'analisi di query ('EXPLAIN PLAIN', http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/ex_plan.htm) per vedere come il DBMS esegue la query. – outis

+0

Come nota a margine, perché 'selezionare *' quando si potrebbe semplicemente 'selezionare * da (selezionare a. *, Rownum rn da table_foo a dove rownum <= 3) dove rn> = 2'? –

risposta

4

La mia comprensione è che l'assegnazione del rownum avviene dopo (o 'come') la riga è selezionata, quindi qualsiasi query 'ROWNUM> = n' con n maggiore di 1 causerà problemi. Ciò che mi è stato spiegato è che la prima riga è vista; è Rownum 1, quindi non soddisfa i criteri e viene gettato via. La riga successiva è guardata; sarà ancora rownum 1 poiché il set di risultati è vuoto e non soddisfa i criteri e viene gettato via. Questo processo continua fino a quando tutte le righe sono state lette e rifiutate.

La query di lunga durata produce effettivamente dati? O l'hai sempre ucciso prima che fosse completato?

+0

La risposta sarà sì - se ha ROWNUM> = 2 (vale a dire qualsiasi predicato che restituisce FALSE quando ROWNUM = 1) la query eseguirà semplicemente l'intero set di dati e non restituirà nulla. –

+0

In realtà ho provato questo e sì, la query verrà semplicemente eseguita fino a quando tutte le righe sono esaurite e non restituiscono nulla. Quindi, in sostanza, le domande in questione non sono identiche. –

1

ROWNUM è una pseudocolonna (non una colonna reale) disponibile in una query. A ROWNUM saranno assegnati i numeri 1, 2, 3, 4, ... N, dove N è il numero di righe nel set con cui ROWNUM è usato. Nel primo caso, stai tagliando il numero di righe immediatamente, e nella seconda devi cercare tutto per tagliare cose più grandi di 2.

Problemi correlati