IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Oracle Discussion :

[9i]Comment optimiser une jointure sur une sous requete ?


Sujet :

Oracle

  1. #1
    Membre habitué
    Inscrit en
    Octobre 2005
    Messages
    125
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 125
    Points : 125
    Points
    125
    Par défaut [9i]Comment optimiser une jointure sur une sous requete ?
    Bonsoir a tous,
    J'ai un doute sur la maniere d'optimiser une requete utilisant une sous-requete. La table de ma sous-requete sur laquelle je veux faire le lien externe possede un index et lorsque je regarde le plan d'execution, je vois qu'a l'interieur de ma sous-requete, Oracle fait un INDEX FULL SCAN au lieu d'un INDEX RANGE SCAN.

    Comment puis-je optimiser ceci ?

    Voici un exemple pour reproduire mon cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    CREATE TABLE LIEN (
      CLE_ORI  NUMBER,
      CLE_DEST NUMBER,
      CONSTRAINT PK_LIEN_ORI_DEST PRIMARY KEY (CLE_ORI, CLE_DEST)
    );
     
    CREATE TABLE CAISSE (
      CLE  NUMBER PRIMARY KEY,
      TAILLE NUMBER
    );
     
    SELECT /*+ORDERED INDEX(SUB.LIEN PK_LIEN_ORI_DEST) */
     C.CLE
    FROM CAISSE C,
    	 (
    		SELECT /*+USE_NL(CAISSE LIEN)*/ LIEN.CLE_ORI, CAISSE.TAILLE
    		FROM LIEN,
    			 CAISSE
    		WHERE LIEN.CLE_DEST = CAISSE.CLE
    	) SUB
    WHERE SUB.CLE_ORI(+) = C.CLE
    AND C.CLE BETWEEN 123456 AND 456123
    AND SUB.TAILLE IS NULL;
    Evidemment je ne peux pas eviter d'avoir ma sous requete, sinon le probleme ne se poserait pas. (bien que dans l'exmple ci dessus il soit facile d'eviter la sous-requete).

    Quand je regarde le plan d'execution, j'ai ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Operation	Object Name	Rows	Bytes	Cost	TQ	In/Out	PStart	PStop
     
    SELECT STATEMENT		1  	 	109  	 	 	 	 
      FILTER		  	 	 	 	 	 	 
        NESTED LOOPS OUTER		  	 	 	 	 	 	 
          INDEX RANGE SCAN	SYS_C0029448	1  	39  	2  	 	 	 	 
          VIEW		1  	26  	108  	 	 	 	 
            NESTED LOOPS		67  	3 K	108  	 	 	 	 
              INDEX FULL SCAN	PK_LIEN_ORI_DEST	82  	2 K	26  	 	 	 	 
              TABLE ACCESS BY INDEX ROWID	CAISSE	1  	26  	1  	 	 	 	 
                INDEX UNIQUE SCAN	SYS_C0029448	1
    Donc j'ai bien un INDEX FULL SCAN sur ma vue au lieu d'un RANGE et ce malgre le "HINT" specifie au debut de la requete.

    Du coup les performance s'en ressentent bcp et je me demande bien comment indiquer a Oracle d'eviter le FULL SCAN dans ma sous-requete ?

    Merci d'avance pour vos reponse. 8)

  2. #2
    Membre éprouvé Avatar de Yorglaa
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    845
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2004
    Messages : 845
    Points : 931
    Points
    931
    Par défaut
    essaye de mettre cette clause
    DANS la sous-requête... et pas dans le requête pricipale !

    plus ta sous-requête sera restrictive et moins tu aura de lignes sur lesquelles faire ta jointure externe.
    Il est plus facile de voir les signes avant-coureurs après coup que l'inverse !

    Yorglaa

  3. #3
    Membre habitué
    Inscrit en
    Octobre 2005
    Messages
    125
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 125
    Points : 125
    Points
    125
    Par défaut
    Merci Yorglaa pour ta suggestion, certes je peux avoir ma sous-requete la plus restrictive possible (ici le TAILLE IS NULL n'est qu'un exemple), cependant le but ici etait de voir comment attaquer l'index d'une de mes tables de ma sous-requete depuis ma requete principale

    Donc oui je pourrais restreindre ma sous-requete, mais mes restrictions sont un peu plus complexes que mon exemple ce qui fait que j'ai bcp plus de tables et jointures impliquees, ce que je voulais essayer d'eviter par l'usage de l'index...

  4. #4
    Membre expert
    Avatar de LeoAnderson
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 2 938
    Points : 3 199
    Points
    3 199
    Par défaut
    Tout d'abord, je ne suis pas un fan des hint car en cas de migration, c'est la galère à maitenir, reprendre avec des effets de bords imprévus...
    Une requête bien écrite avec un bon schéma ne doit, à mon avis, presque jamais nécessiter de hints.

    Et même si votre cas réel est plus complexe que l'exemple donné, avez-vous essayé la proposition de Yorglaa ?
    C'est à dire de restreindre au MAXIMUM les lignes retournées par le sous-select.

    De plus, je pense que vous devriez pouvoir remplacer le sous-select par jointure externe normal, quite à avoir 2 fois "CAISSE" dans le FROM.
    Mais après, tout dépend de la volumétrie....

    Question bête : Les statistiques sont collectées régulièrement et sont à jour ?

  5. #5
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    Citation Envoyé par LeoAnderson
    Tout d'abord, je ne suis pas un fan des hint car en cas de migration, c'est la galère à maitenir, reprendre avec des effets de bords imprévus...
    +1 il faut préférer les outlines autant que possible

  6. #6
    Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 63
    Points : 59
    Points
    59
    Par défaut
    Tiens au passage une autre question :

    Comment fait-on pour voir les plans d'exécutions qui se passent dans une bas Oracle ?

  7. #7
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073

  8. #8
    Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 63
    Points : 59
    Points
    59
    Par défaut
    MERCI !!

  9. #9
    Membre éprouvé Avatar de Yorglaa
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    845
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2004
    Messages : 845
    Points : 931
    Points
    931
    Par défaut
    Citation Envoyé par LeoAnderson
    ...
    De plus, je pense que vous devriez pouvoir remplacer le sous-select par jointure externe normal, quite à avoir 2 fois "CAISSE" dans le FROM.
    Mais après, tout dépend de la volumétrie....
    hummm ça dépend certainement des restrictions à apporter... (vu qu'on ne connait pas le cas réel)
    Si le sous-select contient des restrictions sous forme de IN, NOT IN, EXISTS ou NOT EXISTS avec des sous-selects, on ne peut plus faire directement la jointure externe sur ce genre de restriction. Du coup il est normal de faire toutes ces restriction dans une vue en ligne et d'ensuite d'y appliquer la jointure externe finale
    Il est plus facile de voir les signes avant-coureurs après coup que l'inverse !

    Yorglaa

  10. #10
    Membre régulier
    Inscrit en
    Mars 2006
    Messages
    88
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 88
    Points : 95
    Points
    95
    Par défaut
    Citation Envoyé par Fred_D
    Citation Envoyé par LeoAnderson
    Tout d'abord, je ne suis pas un fan des hint car en cas de migration, c'est la galère à maitenir, reprendre avec des effets de bords imprévus...
    +1 il faut préférer les outlines autant que possible
    +1.
    99% du code PL/SQL peut être optimisé facilement avec ou sans l'aide d'un DBA et ne nécessite pas de hints. Seuls des cas très tordus peuvent nécessiter des hints. Après bonjour la galère pour comprendre le comportement du SQL quand il tourne sur différents environnements.

    @+,
    NicK.

  11. #11
    Membre actif
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2005
    Messages
    250
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2005
    Messages : 250
    Points : 277
    Points
    277
    Par défaut Re: [9i]Comment optimiser une jointure sur une sous requete
    Il me semble qu'il y a un probleme dans l'écriture de tes hints... Ce qui expliquerait qu'Oracle n'en tienne pas compte.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT /*+ORDERED INDEX(SUB.LIEN PK_LIEN_ORI_DEST) */
     C.CLE
    FROM CAISSE C,
    	 (
    		SELECT /*+USE_NL(CAISSE LIEN)*/ LIEN.CLE_ORI, CAISSE.TAILLE
    ...
    Et si tu rajoutais un espace entre le /*+ et ORDERED ou USE_NL ???

    Ceci dit, l'optimiseur d'Oracle est très performant si tu as des statistiques fraiches et complètes et il se peut qu'il te propose une meilleure solution que celle que tu envisages...
    Je te conseille de faire un trace et de vérifier que ta solution est bien la meilleure avant de l'imposer à Oracle avec des hints...
    Dyvim

  12. #12
    Membre habitué
    Inscrit en
    Octobre 2005
    Messages
    125
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 125
    Points : 125
    Points
    125
    Par défaut
    Bonjour a tous,
    Merci beaucoup pour tout vos conseils

    Tout d'abord, les stats sont a jour et actualisee toutes les nuits.
    Oracle n'a pas de pb qu'il y ait ou pas d'espace entre /* et le + des hints.

    Concernant le cas reel, je ne peux pas me permettre de le sortir d'un sub select sinon j'ai un outer join sur 2 tables et evidemment ca passe pas

    Par contre sincerement concernant les hints, je ne sais pas trop quoi penser.
    Je suis tout a fait d'accord que c'est un peu forcer Oracle a faire son boulot d'une autre maniere et donc pas forcement tres juste de proceder ainsi. Cependant je dois vous avouer que je ne suis en rien un expert d'Oracle. Cela fait juste 4 ans que je travaille avec cette BDD et de ma humble experience sur la base de ma boite (qui est surement configuree d'une maniere differente), j'avoue que j'ai eu des resultats plutot efficaces que je n'aurai jamais pu avoir sans utiliser les HINTs. Cepedant Leo, il y a des chances que le schema ne soit pas si optimum que cela, malheureusement je suis dans l'impossibilite totale de le changer (et meme si je pouvais, je pense que je prefererai ne pas le faire)...

    Ce qui m'etonnait dans mon exemple, c'est le fait de ne pas pouvoir acceder a un RANGE SCAN sur l'index de ma sous requete.

    Concernant une eventuelle migration, nous en avons deja effectue une pour passer de 8 a 9 et ca c'est passe sans trop de pb. J'ai juste reviser les grosses requetes et changer un tout petit peu certains Hints, mais sincerement ca s'est fait sans probleme majeur, donc je pense que je continuerai ainsi, sauf si qqun me donne une tres bonne raison de ne pas le faire et surtout si un DBA vient jeter un oeil dans notre base pour nous dire que ca va pas du tout

    C'est clair qu'il nous manque un BA en interne, car pour le moment seul un consultant vient optimiser/faire le menage de tps en tps

    Une fois de plus, merci pour vos suggestions, je vais continuer a regarder tout cela avec attention.

  13. #13
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par tostinni
    Oracle n'a pas de pb qu'il y ait ou pas d'espace entre /* et le + des hints.
    Attention : l'explain plan d'Oracle est différent de l'explain plan de TOAD.
    On s'est apperçut avec TKPROF que les "/*+"..., oracle supprimait le "+" et que donc : pas de HINT.
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  14. #14
    Membre habitué
    Inscrit en
    Octobre 2005
    Messages
    125
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 125
    Points : 125
    Points
    125
    Par défaut
    Citation Envoyé par McM
    Citation Envoyé par tostinni
    Oracle n'a pas de pb qu'il y ait ou pas d'espace entre /* et le + des hints.
    Attention : l'explain plan d'Oracle est différent de l'explain plan de TOAD.
    On s'est apperçut avec TKPROF que les "/*+"..., oracle supprimait le "+" et que donc : pas de HINT.
    Merci pour l'info, cependant je ne mettais jamais d'espace a cet endroit donc ca devrait aller.

    Par contre qd tu dis que l'explain plan de TOAD et d'oracle est different, tu veux dire quoi exacetement ?
    Je ne peux pas me servir de TOAD pour optimiser ma requete ???

  15. #15
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Après vérifs, on était à l'époque en 8.1.7
    Maintenant on est en 9i, et après mes tests, ça marche

    Voici la trace du SELECT de l'époque (debut 2004)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT /*+RULE */BL_BLOC || '.'  || CH_CHAMP ...
    TKPROF:
    SELECT /*+ ULE */BL_BLOC || '.' || CH_CHAMP V_ITEM,PG_CODFAMACTIO V_ACTION
    FROM PCFCHAMP
    WHERE CH_LOGIN = :b1
    AND BL_NOMFCT = :b2
    AND BL_FORME = :b3
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Sous TOAD, ça affichait bien le mode RULE.
    Notre conclusion avec le DBA (après de multiples tests) étaient :
    1/ TOAD reformatait les HINTS pour mettre des espaces
    2/ L'optimiseur Oracle nécessitait un espace entre le /*+ et le hint
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  16. #16
    Membre actif
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2005
    Messages
    250
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2005
    Messages : 250
    Points : 277
    Points
    277
    Par défaut
    Citation Envoyé par McM
    Notre conclusion avec le DBA (après de multiples tests) étaient :
    1/ TOAD reformatait les HINTS pour mettre des espaces
    2/ L'optimiseur Oracle nécessitait un espace entre le /*+ et le hint
    Je ne me serais pas permis de donner cette info si elle n'était pas fiable...
    Elle m'a été donnée lors d'une formation chez Oracle sur le SQL Tuning...
    Il faut un espace entre /*+ et le hint...
    Dyvim

Discussions similaires

  1. [WD18] Metre une colonne d'une Table sur une ligne d'une autre Table
    Par Totophe2 dans le forum WinDev
    Réponses: 2
    Dernier message: 22/11/2013, 12h58
  2. Impact d'une jointure sur une base de données
    Par Immobilis dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 22/06/2009, 12h11
  3. [SQL Server] Filtré sur une table avant une jointure externe
    Par TangoZoulou dans le forum Langage SQL
    Réponses: 2
    Dernier message: 06/11/2006, 15h52
  4. Réponses: 5
    Dernier message: 18/07/2006, 15h32
  5. Réponses: 4
    Dernier message: 25/07/2005, 14h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo