Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Unter welchen Bedingungen erhöht ROWNUM=1 die Leistung in einer Existiert-Abfrage erheblich?

Es verbessert die Leistung erheblich (im Durchschnitt um mehrere zehn Prozent) bei Abfragen, die nicht durch eine einfache Einzelindexsuche gelöst werden können, z. Tabellenverknüpfungen. Es besteht jedoch die Möglichkeit, Daten-/Anwendungsfehler zu verbergen.

Lassen Sie uns eine Tabelle haben:

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

--benutze PK absichtlich nicht, um das Beispiel so einfach wie möglich zu machen. Die Auffüllung wird verwendet, um die tatsächliche Datenlast in jedem Datensatz zu simulieren

mit vielen Aufzeichnungen:

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

Wenn Sie jetzt so etwas wie

fragen
select 1 into ll_exists
from t where id = 5;

der DB muss die ganze Tabelle durchgehen, ob er den einzigen passenden Datensatz im ersten Datenblock (den wir übrigens nicht wissen können, weil er auf viele verschiedene Arten eingefügt werden könnte) oder im letzten gefunden hat. Das liegt daran, dass es nicht weiß, dass es nur einen übereinstimmenden Datensatz gibt. Auf der anderen Seite, wenn Sie ... und rownum =1 verwenden, kann es aufhören, Daten zu durchlaufen, nachdem der Datensatz gefunden wurde, weil Sie ihm gesagt haben, dass es keinen anderen passenden Datensatz gibt (oder nicht benötigt).

Der Nachteil ist, dass Sie mit der Rownum-Einschränkung möglicherweise undeterministische Ergebnisse erhalten, wenn die Daten mehr als einen möglichen Datensatz enthalten. Wenn die Abfrage war

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

dann bekomme ich vielleicht von der DB Antwort 1 sowie 3 sowie 123 ... Bestellung ist nicht garantiert und das ist die Folge. (Ohne die rownum-Klausel würde ich eine TOO_MANY_ROWS-Ausnahme erhalten. Es hängt von der Situation ab, welche schlimmer ist)

Wenn Sie wirklich fragen wollen, welche Tests existieren, dann SCHREIBEN SIE ES SO.

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;