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 :

Lenteur sur une requête avec jointure


Sujet :

SQL Oracle

  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut Lenteur sur une requête avec jointure
    Bonjour à tous,


    J'ai des clients, des dépôts, des visites.

    Un client est rattaché à un dépôt.
    Une visite est rattaché à un client et à un dépôt.

    J'ai besoin de récupérer l'ensemble des clients qui, soit son rattachés à un dépôt particulier, soit on eu une visite qui elle est rattaché à ce dépôt.

    La sélection des clients du dépôt est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT * FROM TBClients WHERE CDepId=25
    La sélection des clients qui ne sont pas rattachés à ce dépôt mais qui ont eu une visite rattaché au dépôt est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT c2.ClientId FROM TBClients c2 WHERE c2.CDepId != 25 AND c2.ClientID IN
    (
        SELECT DISTINCT VClientId FROM TBVisites WHERE VDepId = 25
    )
    Ces deux requêtes sont rapides à exécuter. Par contre, j'aimerai n'en faire qu'une :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT * FROM TBClients WHERE CDepId=25 or ClientId in
    (
        SELECT DISTINCT VClientId FROM TBVisites WHERE VDepId = 25
    )
    Et là ça met 30 secondes à s'exécuter...


    Comment je peux faire pour avoir une seule requête ayant la rapidité des deux premières ?


    Merci beaucoup;

    A bientôt
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Une requête UNION peut-être ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SELECT ClientId 
    FROM TBClients 
    WHERE CDepId=25
     
    UNION
     
    SELECT c2.ClientId 
    FROM TBClients c2 
    WHERE c2.CDepId != 25 AND c2.ClientID IN
    (
        SELECT DISTINCT VClientId 
        FROM TBVisites 
        WHERE VDepId = 25
    )
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Membre à l'essai
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    14
    Détails du profil
    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 14
    Points : 16
    Points
    16
    Par défaut
    Essaye plutot ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT * FROM TBClients WHERE CDepId=25 
    Union 
    SELECT * FROM TBClients C WHERE EXISTS (SELECT  1 FROM TBVISITES T
                                                                WHERE T.VClientId= C.ClientId
                                                                   AND VDepId = 25
                                                                )
    - Tu peux également utilisé une fonction
    - Il est preférable d'utiliser EXISTS au Lieu de IN

  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
    c'est un jeu de devinettes ?
    cool, j'adore ça !

    blague à part, on doit deviner les indexes ? les explains plans ? les volumétries ?

    l'optimisation de requête, ça ne se fait pas au hasard !!!

  5. #5
    Membre confirmé Avatar de miloux32
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    545
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 545
    Points : 565
    Points
    565
    Par défaut
    Citation Envoyé par bertrand_nt Voir le message
    Essaye plutot ceci :

    SELECT * FROM TBClients WHERE CDepId=25
    Union
    SELECT * FROM TBClients C WHERE EXISTS (SELECT 1 FROM TBVISITES T
    WHERE T.VClientId= C.ClientId
    AND VDepId = 25
    )


    - Tu peux également utilisé une fonction
    - Il est preférable d'utiliser EXISTS au Lieu de IN

    Ah non pas d'accord !!!
    On m'a toujours dit d'éviter absolument exist dans un SELECT , il est plutot concu pour un update , mais presque tous les exist dans un SELECT peuvent se remplacer par une jointure !
    C'est pas parce que ca marche que c'est bon!!
    Pensez au bouton "Résolu"
    Je ne réponds pas en privé aux questions

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Bé en tout cas ça fonctionne bien là avec l'union.


    Merci
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Points : 342
    Points
    342
    Par défaut
    Citation Envoyé par miloux32 Voir le message
    Ah non pas d'accord !!!
    On m'a toujours dit d'éviter absolument exist dans un SELECT , il est plutot concu pour un update , mais presque tous les exist dans un SELECT peuvent se remplacer par une jointure !
    Ben oui, c'est même souvent ce que fait Oracle en terme de plan d'execution ! S'il est possible de remplacer exists par une jointure, il fait "comme si". Et ce depuis toujours. Donc, ce n'est pas la peine de s'en priver.

    Et quand ce n'est pas transformable elegament avec une jointure parce que la clause exists ramene plus d'une ligne, les algorithmes utilisé par exists savent s'arreter à la première ligne trouvée, ce qui est parfaitement performant, beaucoup plus qu'un group by artificiel.

    Bref, le "on" qui t'a dit ça se prive ( et te prive) d'une fonctionnalité bien efficace et traite des problèmes simple d'une façon bien compliquée.

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Est-ce qu'il y a des bouquins sur l'utilisation du SQL ?

    Car moi... J'y connais rien en optimisation de requête. Juste les trucs auquel j'arrive à penser, c'est mettre les conditions qui sont suceptible d'etre négative au début des critères.

    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT * FROM TABLE WHERE CRIT1=VALEUR1 AND CRIT2=VALEUR2
    Si le critère 2 a de forte chance d'être négatif, je préfèrerai le mettre en premier.
    Je fais ça en programmation, mais je sais pas si ça fait quelque chose en SQL.

    Y'aura pas un bon bouquin qui expliquerai les bonnes pratique du SQL ?


    Et est-ce que ces bonnes pratiques sont dépendantes du SGBDR utilisé ?

    Merci,

    A bientôt
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  9. #9
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Regarde dans les tutoriels de Développez.com
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Points : 342
    Points
    342
    Par défaut
    Citation Envoyé par mister3957 Voir le message
    Est-ce qu'il y a des bouquins sur l'utilisation du SQL ?

    Car moi... J'y connais rien en optimisation de requête. Juste les trucs auquel j'arrive à penser, c'est mettre les conditions qui sont suceptible d'etre négative au début des critères.

    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT * FROM TABLE WHERE CRIT1=VALEUR1 AND CRIT2=VALEUR2
    Si le critère 2 a de forte chance d'être négatif, je préfèrerai le mettre en premier.
    Je fais ça en programmation, mais je sais pas si ça fait quelque chose en SQL.

    Y'aura pas un bon bouquin qui expliquerai les bonnes pratique du SQL ?


    Et est-ce que ces bonnes pratiques sont dépendantes du SGBDR utilisé ?

    Merci,

    A bientôt
    Il fut un temps ou ces considérations faisaient sens, quand l'optimiseur était basé sur des règles. L'ordre des tables dans le from et celui des conditions des clause where pouvaient changer le plan. C'est beaucoup moins vrai, voire pas vrai du tout, avec les optimiseurs statistiques.

  11. #11
    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 miloux32 Voir le message
    Ah non pas d'accord !!!
    On m'a toujours dit d'éviter absolument exist dans un SELECT , il est plutot concu pour un update , mais presque tous les exist dans un SELECT peuvent se remplacer par une jointure !
    en réalité il n'y a pas de règle Si la sous-requête du IN ramène peu de ligne alors faut utiliser le IN, sinon le EXISTS est souvent plus avantageux. Mais faut tester

    Et le IN comporte un piége puisque les valeurs NULL sont exclues

  12. #12
    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 jmguiche Voir le message
    Il fut un temps ou ces considérations faisaient sens, quand l'optimiseur était basé sur des règles. L'ordre des tables dans le from et celui des conditions des clause where pouvaient changer le plan. C'est beaucoup moins vrai, voire pas vrai du tout, avec les optimiseurs statistiques.
    pas tout à fait... l'ordre peu quand même être important pour les grosses requêtes parce que le nombre de permutations pour trouver le plan d'exécution n'est pas infini... du coup ça peut éviter que le bon plan soit exclu

  13. #13
    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 mister3957 Voir le message
    Y'aura pas un bon bouquin qui expliquerai les bonnes pratique du SQL ?
    si tu commençais par donner les infos demandées par LeoAnderson ce serait pas mal déjà

  14. #14
    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
    j'arrive pas à croire que le sujet soit taggué comme résolu alors qu'on parle toujours dans le vide !

    Si il était possible d'optimiser toutes les requêtes par une ré-écriture de codes ou remplace NOT IN pas MINUS, ne croyez-vous pas que le moteur ferait ça tout seul ?
    S'il la règle absolue existait, même complexe avec 5000 IF imbriqués, elle serait implémentée en automatique. Et donc, la question ne se poserait pas.

    Or, la question se pose. Et il n'y a pas de règle universelle.
    C'est pour ça qu'on a besoin d'un minimum d'infos telles que demandées plus haut !

  15. #15
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Une étude d'optimisation assez édifiante :

    Voir aussi son article sur l'optimisation et notamment les chapitres 8 et 9.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Points : 342
    Points
    342
    Par défaut
    Citation Envoyé par mister3957 Voir le message
    Est-ce qu'il y a des bouquins sur l'utilisation du SQL ?

    Car moi... J'y connais rien en optimisation de requête. Juste les trucs auquel j'arrive à penser, c'est mettre les conditions qui sont suceptible d'etre négative au début des critères.

    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT * FROM TABLE WHERE CRIT1=VALEUR1 AND CRIT2=VALEUR2
    Si le critère 2 a de forte chance d'être négatif, je préfèrerai le mettre en premier.
    Je fais ça en programmation, mais je sais pas si ça fait quelque chose en SQL.

    Y'aura pas un bon bouquin qui expliquerai les bonnes pratique du SQL ?


    Et est-ce que ces bonnes pratiques sont dépendantes du SGBDR utilisé ?

    Merci,

    A bientôt
    Pour comprendre comment ça marche sous oracle, la doc oracle, c'est pas mal. (performance und tuning).
    En effet, les problèmes d'optimisations et les bonnes pratiques peuvent varier d'un SGBD à un autre, et même, pour un même sgbd, cela peu changer au fil des versions, soit radicalement : passage d'un optimiseur regle a un optimiseur stat, soit parce qu'il y a des améliorations.

  17. #17
    Membre actif Avatar de Jean_Benoit
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 499
    Points : 234
    Points
    234
    Par défaut Réduction effective du COST
    J'ai testé la requête originale avec une base de 100000 lignes,

    le cost est de 150

    Ensuite la requête avec UNION et EXISTS, et un index sur la FK N° de dépot dans la table des clients

    le cost est de 15

    Ensuite j'ai placé la sous requête dans une clause WITH,

    le cost est de 10

    WITH customer_visites AS (
    SELECT
    DISTINCT custno as customer_v
    FROM Visites
    WHERE depotno = 1010
    )
    SELECT c.*
    from customer_visites cv, customers c
    where custno = customer_v
    or c.depotno = 1010;

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Aide sur une requête avec jointure et LIMIT 1
    Par mister3957 dans le forum Langage SQL
    Réponses: 7
    Dernier message: 28/06/2013, 20h17
  2. Réponses: 16
    Dernier message: 20/01/2011, 12h45
  3. Besoin aide sur une requête avec jointure
    Par PoichOU dans le forum Requêtes
    Réponses: 3
    Dernier message: 31/08/2010, 18h32
  4. Aide sur une requête avec jointure..
    Par WeDgEMasTeR dans le forum Requêtes
    Réponses: 7
    Dernier message: 10/11/2009, 18h09
  5. optimisation d'une requête avec jointure
    Par champijulie dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 07/07/2005, 09h45

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