Oracle
 sql >> Base de données >  >> RDS >> Oracle

Dans quelles conditions ROWNUM =1 augmente-t-il considérablement les performances dans une requête de style existant

Il améliore considérablement les performances (moyenne de dizaines de pour cent) sur les requêtes qui ne peuvent pas être résolues par une simple recherche d'index unique, par ex. jointures de table. Cependant, il est possible de masquer les erreurs de données/d'application.

Faisons un tableau :

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

-- intentionnellement, n'utilisez pas PK pour rendre l'exemple aussi simple que possible. Le rembourrage est utilisé pour simuler le chargement réel des données dans chaque enregistrement

avec de nombreux enregistrements :

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

Maintenant, si vous demandez quelque chose comme

select 1 into ll_exists
from t where id = 5;

la base de données doit parcourir toute la table si elle a trouvé le seul enregistrement correspondant dans le premier bloc de données (ce que nous ne pouvons d'ailleurs pas savoir car il peut être inséré de différentes manières) ou dans le dernier. C'est parce qu'il ne sait pas qu'il n'y a qu'un seul enregistrement correspondant. D'un autre côté, si vous utilisez ... et rownum =1, il peut arrêter de parcourir les données une fois l'enregistrement trouvé car vous lui avez dit qu'il n'y a pas (ou pas besoin) d'autre enregistrement correspondant.

L'inconvénient est qu'avec la contrainte rownum, vous pouvez obtenir des résultats indéterministes si les données contiennent plus d'un enregistrement possible. Si la requête était

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

alors je peux recevoir de la DB la réponse 1 ainsi que 3 ainsi que 123... la commande n'est pas garantie et c'est la conséquence. (sans la clause rownum, j'obtiendrais une exception TOO_MANY_ROWS. Cela dépend de la situation, laquelle est la pire)

Si vous voulez vraiment une requête qui teste l'existence, ÉCRIVEZ-LA DE CETTE FAÇON.

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;