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

SQL Oracle Discussion :

Question sur un plan d'exécution


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut Question sur un plan d'exécution
    Bonjour !

    Ma requête : (retouchée pour garder l'anonymat )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT *
    FROM MaTable A JOIN MaTable B
      ON a.id_compte = b.id_compte
     AND a.etat = b.etat
    WHERE a.id_compte = (SELECT id_compte FROM TableRef C WHERE nom_compte = 'X')
    ORDER BY a.unchamp
    Donne le plan d'exécution suivant :
    SELECT STATEMENT 1 142 179K
    SORT ORDER BY 1 142 179K
    HASH JOIN 1 142 179K
    TABLE ACCESS BY INDEX ROWID MaTable 3802 193K 1104
    INDEX RANGE SCAN IndexTable1 15209 79
    TABLE ACCESS BY INDEX ROWID TableRef 1 33 2
    INDEX UNIQUE SCAN IndexRef1 1 1
    TABLE ACCESS FULL MaTable 1897K 162M 178K
    C'est pas très lisible, mais l'important est de voir que le CBO choisit FTS alors que ça aurait été sympa de lire IndexTable1...

    Ce qu'il faut noter, c'est que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (SELECT id_compte FROM TableRef C WHERE nom_compte = 'X')
    Renvoie une seule ligne. (y'a un index unique)

    Maintenant, si on substitue directement la valeur, ça donne la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT *
    FROM MaTable A JOIN MaTable B
      ON a.id_compte = b.id_compte
     AND a.etat = b.etat
    WHERE a.id_compte = 378
    ORDER BY a.unchamp
    Et là, le plan correspondant est :
    0 SELECT STATEMENT 1 142 2217
    1 SORT ORDER BY 1 142 2217
    2 HASH JOIN 1 142 2211
    3 TABLE ACCESS BY INDEX ROWID MaTable 3802 193K 1104
    4 INDEX RANGE SCAN IndexTable1 15209 79
    5 TABLE ACCESS BY INDEX ROWID MaTable 3802 334K 1104
    6 INDEX RANGE SCAN IndexTable1 15209 79
    => C'est ce dont on a toujours rêvé !

    Est-ce que quelqu'un sait pourquoi ?
    A vrai dire, je n'ai pas ce problème en général : je stocke l'identifiant du compte dans une variable. Mais il s'agit là d'une vieille requête...

    Ce que j'aimerais, c'est avoir une explication rationnelle du phénomène, ce qui me fournirait des arguments solides pour ensuite convaincre mes amis de faire attention à ce "détail".

    PS : comme on a en ce moment des petits problèmes de perf, on a un peu de mal à savoir ce qui est vraiment du à des requêtes pourries, ou a des problèmes de stats, ou des paramètres systèmes, ...

    Merci !

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Citation Envoyé par pacmann Voir le message
    C'est pas très lisible, mais l'important est de voir que le CBO choisit FTS alors que ça aurait été sympa de lire IndexTable1...

    Ce qu'il faut noter, c'est que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (SELECT id_compte FROM TableRef C WHERE nom_compte = 'X')
    Renvoie une seule ligne. (y'a un index unique)
    Notez bien que le FTS a été fait sur la table de référence.

    Vous avez, j'imagine, un index unique sur TableRef.id_compte mais aucun index sur TableRef.nom_compte, qui est la valeur filtrée.

    Essayez un index (pas forcément unique) sur TableRef.nom_compte et remontrez-nous le plan.

  3. #3
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Oops, je me suis planté quand j'ai remplacé les noms de mes tables par leur fausses identités respectives...

    Par ailleurs, il y a bien un index sur la grosse table : les deux côtés de la jointure accèdent à la même table, selon les mêmes critères. Et la première fois, l'accès est bien fait par l'index sur le compte...

    (j'édite le poste initial pour rétablir la vérité)

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Autre tentative, je n'y crois pas beaucoup mais essayons :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE a.id_compte = (SELECT C.id_compte FROM TableRef C WHERE C.nom_compte = 'X')
    Que donnerait le plan d'exécution de la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT *
    FROM MaTable A JOIN MaTable B
      ON a.id_compte = b.id_compte
     AND a.etat = b.etat
        JOIN TableRef c
      ON a.id_compte = c.id_compte
    WHERE c.nom_compte = 'X'
    ORDER BY a.unchamp

  5. #5
    Membre Expert Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Non plus !

    (J'ai tenté les deux variantes)

    Et en fait, le plus important n'est pas la requête gagnante, puisqu'on l'a déjà...
    (à savoir commencer par récupérer l'identifiant dans une variable, puis passer la variable dans la jointure).
    Le fait est surtout que la différente de comportement me surprend beaucoup...

  6. #6
    Membre Expert Avatar de fatsora
    Profil pro
    Inscrit en
    Février 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 1 103
    Par défaut
    quelle est ta version Oracle

    les parameters cursor_sharing , optimizer_mode etc

    voir

    http://www.oracloid.com/2006/07/bind...no-histograms/

Discussions similaires

  1. [2008R2] Question sur un plan d'éxécution
    Par KyoshiroKensei dans le forum MS SQL Server
    Réponses: 11
    Dernier message: 20/08/2014, 12h43
  2. Que signifie le petit symbole sur le plan d'exécution ?
    Par cmako dans le forum MS SQL Server
    Réponses: 10
    Dernier message: 01/09/2009, 15h30
  3. Réponses: 11
    Dernier message: 28/04/2008, 16h29
  4. Réponses: 7
    Dernier message: 11/09/2006, 14h23
  5. Réponses: 12
    Dernier message: 22/06/2006, 10h26

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