Oracle
 sql >> Database >  >> RDS >> Oracle

In quali condizioni ROWNUM=1 aumenta significativamente le prestazioni in una query syle esistente

Migliora significativamente le prestazioni (media delle decine di percento) su query che non possono essere risolte con una semplice ricerca di un singolo indice, ad es. join di tabelle. Tuttavia, ha il potenziale per nascondere dati/errore dell'applicazione.

Facciamo una tabella:

create table t (id number(10,0), padding varchar2(1000));  

--intenzionalmente non usare PK per rendere l'esempio il più semplice possibile. Il riempimento viene utilizzato per simulare il carico di dati reale in ogni record

con molti record:

insert into t (id, padding)
select rownum, rpad(' ', 1000) from dual connect by level < 10000

Ora se chiedi qualcosa come

select 1 into ll_exists
from t where id = 5;

il DB deve scorrere l'intera tabella se ha trovato l'unico record corrispondente nel primo blocco dati (che tra l'altro non possiamo sapere perché potrebbe essere inserito in molti modi diversi) o nell'ultimo. Questo perché non sa che esiste un solo record corrispondente. D'altra parte, se usi ... e rownum =1, può interrompere l'attraversamento dei dati dopo che il record è stato trovato perché gli hai detto che non c'è (o non è necessario) un altro record corrispondente.

Lo svantaggio è che con il vincolo rownum potresti ottenere risultati non deterministici se i dati contengono più di un possibile record. Se la query era

select id into ll_id
from t where mod (id, 2) = 1
and rownum = 1;

quindi potrei ricevere dalla risposta DB 1 oltre a 3 e 123 ... l'ordine non è garantito e questa è la conseguenza. (senza la clausola rownum otterrei un'eccezione TOO_MANY_ROWS. Dipende dalla situazione qual è la peggiore)

Se vuoi davvero una query che verifica l'esistenza, SCRIVI IN QUEL MODO.

begin

select 'It does' 
  into ls_exists
from dual where
exists (your_original_query_without_rownum);

do_something_when_it_does_exist
exception
  when no_data_found then
    do_something_when_it_doesn't_exist
end;