SQL - Optimisation

Résolu/Fermé
sebv33 - 20 nov. 2008 à 11:20
 sebv33 - 20 nov. 2008 à 15:57
Bonjour,

je suis une brêle en SQL.

dans un trigger sous Oracle j'ai deux requêtes à la suite:

UPDATE magasin mag
SET mag.dernier_statut = :new.CDSTATUT ,
mag.lb_statut = :new.LBSTATUT
WHERE mag.CODE_COMPLET = (substr(:old.LBSTATUT, 27, 20) );

et

select mag.region_fk
INTO region_id
from magasin mag
where mag.CODE_COMPLET = (substr(:old.LBSTATUT, 27, 20) );


CODE_COMPLET est VARCHAR et il y a un index dessus.


Je dois l'optimiser et il y a quelques questions que je me (vous) pose.

- serait-il plus rapide d'effectuer les deux recherches sur la clé primaire de MAGASIN?
- y a-t-il un moyen de ne pas rechercher deux fois la même ligne (une fois pour un update et une fois pour un select)? Si oui, cela améliorerait les performances?

Merci pour votre aide
A voir également:

1 réponse

sandul Messages postés 3927 Date d'inscription jeudi 22 mai 2008 Statut Membre Dernière intervention 8 octobre 2010 723
20 nov. 2008 à 12:04
Salut Seb,

Moi non plus je ne suis pas très bon en optimisation Oracle, mais je crois que, même si tu as un index sur CODE_COMPLET, il peut y avoir un full table scan à cause de mag.CODE_COMPLET = (substr(:old.LBSTATUT, 27, 20) ); ==> le substr ne va pas utiliser l'index. A vérifier cet aspect, donc.

Maintenant, il est vrai que le substr fait référence à la valeur old et il importe de savoir le contexte. Il se peut que dans certains contextes Oracle puisse identifier la ligne sans faire le scan complet de la table...

Du coup, si ce que j'ai dit est vrai, tes requêtes sont pénalisantes en cas de grosse volumétrie de la table magasin. Dans ce cas, contourne (via la clef primaire, si tu peux) l'utilisation de substr sur une colonne de la table.

Si pas de full table scan: utiliser la clef primaire à la place de l'index sur CODE_COMPLET peut être plus performant à cause du fait que le nombre de clusters de lindes dépend du type de champ et de sa taille ==> une primary key sur une colonne INTEGER, par exemple, sera plus compacte en taille disque (et donc elle sera parcourue plus vite) qu'un index sur un varchar2 (300). Sinon, comme tu le sais bien, un rebuild de l'index et sa définition dans son propre tablespace (qui à son tour est définie sue un disque dur différent) peuvent bien améliorer les perfs en cas d'utilisation de l'index.

Pour répondre à ta 2ème question: oui, si tu peux éviter de rechercher 2 fois la même info c'est mieux. Une idée c'est d'utiliser un cursor dans ton trigger défini en tant que SELECT ... FOR UPDATE sur magasin ==> une fois que tu es sur la ligne tu fais UPDATE magasin WHERE CURRENT OF pour ta première requête et pour la deuxième tu as des valeurs en RAM dans le record associé au curseur ouvert (plus besoin de faire le SELECT INTO, donc).

++
0
Merci sandul,

pour info j'ai trouvé comment effectuer une seule requête:

UPDATE magasin mag
SET mag.dernier_statut = :new.CDSTATUT ,
mag.lb_statut = :new.LBSTATUT
WHERE mag.CODE_COMPLET = (substr(:old.LBSTATUT, 27, 20) )
RETURNING mag.region_fk INTO region_id;
0