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 :

[Requête] Problème performance


Sujet :

SQL Oracle

  1. #1
    Membre averti Avatar de GyZmoO
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2006
    Messages : 428
    Points : 301
    Points
    301
    Par défaut [Requête] Problème performance
    Bonjour à tous, je vous expose mon soucis.
    Nous avons une table VENUE et une table PASSAGE. Une venue peut avoir plusieurs passages, un passage n'a qu'une seule venue.
    Un passage possède une date de début, et une date de fin. Pour une venue qui a 3 passages : le passage 1 démarre à D1, termine à D2. Le passage 2 démarre à D2 et se termine à D3. Enfin le passage 3 démarre à D3 et se termine à D4. Avec D1 < D2 < D3 < D4.

    Le but de notre requête est de récupérer pour chaque venue, le premier passage (au sens chronologique) ainsi que le dernier.
    Pour le moment notre requête qui récupère le premier passage ressemble à ça :

    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
     
    SELECT
                    PASSAGE.ID_VENU as idVenue,
                    PASSAGE.DATE_DEBUT as dateDebut
                FROM
                    PASSAGE 
                INNER JOIN
                    (
                        SELECT
                            PASSAGE.ID_VENU,
                            MIN(PASSAGE.DATE_DEBUT) as mini 
                        FROM
                            PASSAGE 
                        GROUP BY
                            PASSAGE.ID_VENU
                    ) INNERTMP 
                        ON INNERTMP.ID_VENU = PASSAGE.ID_VENU 
                        AND INNERTMP.mini  = PASSAGE.DATE_DEBUT
    Seulement, le temps d'exécution se compte en plusieurs dizaines de secondes... Niveau volumétrie, nous avons 2 500 000 venues pour 3 000 000 de passages... Si vous avez une idée/piste d'amélioration, je suis preneur.

    D'avance merci!

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 109
    Points : 28 434
    Points
    28 434
    Par défaut
    Premières pistes d'amélioration :
    1. Créer un index sur PASSAGE(ID_VENU, DATE_DEBUT) s'il n'existe pas encore.
    2. Avoir des statistiques à jour sur ces tuples

    Une requête qui devrait donner les résultats demandés :
    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
    SELECT  ps1.id_venu
        ,   ps1.date_debut  AS dateDebut
        ,   ps1.autresinfos AS PremierPassage
        ,   ps2.date_debut  AS dateFin
        ,   ps2.autresinfos AS DernierPassage
    FROM    passage ps1 
        INNER JOIN
            passage ps2 
            ON  ps1.id_venu = ps2.id_venu
    WHERE   EXISTS 
            (   SELECT  1
                FROM    passage tmp
                WHERE   tmp.id_venu = ps1.id_venu 
                GROUP BY tmp.id_venu
                HAVING  ps1.date_debut  = MIN(tmp.date_debut)
                    AND ps2.date_debut  = MAX(tmp.date_debut)
            )
    ;

  3. #3
    Membre averti Avatar de GyZmoO
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2006
    Messages : 428
    Points : 301
    Points
    301
    Par défaut
    Merci pour ces pistes ! Je teste ça et je reviens dire ce que ça donne

  4. #4
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Points : 1 359
    Points
    1 359
    Par défaut
    Bonjour,

    Pourriez-vous changer légèrement votre requête comme indiqué ci-dessous:

    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
     
    SELECT /*+ qb_name(main) gather_plan_statistics */
            ps1.id_venu
        ,   ps1.date_debut  AS dateDebut
        ,   ps1.autresinfos AS PremierPassage
        ,   ps2.date_debut  AS dateFin
        ,   ps2.autresinfos AS DernierPassage
    FROM    passage ps1 
        INNER JOIN
            passage ps2 
            ON  ps1.id_venu = ps2.id_venu
    WHERE   EXISTS 
            (   SELECT /*+ qb_name(subq) */ 1
                FROM    passage tmp
                WHERE   tmp.id_venu = ps1.id_venu 
                GROUP BY tmp.id_venu
                HAVING  ps1.date_debut  = MIN(tmp.date_debut)
                    AND ps2.date_debut  = MAX(tmp.date_debut)
            )
    ;
    Et poster le plan d’exécution que vous allez obtenir en faisant ceci immédiatement après la fin de votre requête

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select * from table(dbms_xplan.display_cursor(null,null,'allstats all'));
    Je pourrai peut-être vous aider

    Bien à vous
    Mohamed Houri

  5. #5
    Membre averti Avatar de GyZmoO
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    428
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2006
    Messages : 428
    Points : 301
    Points
    301
    Par défaut
    Bonjour et merci pour vos réponses.

    En utilisant la requête fournie par al1_24,

    Les temps d'exécution sont meilleurs (presque divisés par 2).

    Par contre, je ne peux poster le plan d'exécution suite à cette requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select * from table(dbms_xplan.display_cursor(null,null,'allstats all'));
    J'obtiens un joli :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    User has no SELECT privilege on V$SESSION
    Et bien sur je ne peux contacter aucun DBA pour le moment

    Je vais donc continuer à creuser, et peut être ajouter l'index, je vous tiendrai au courant !

    Merci

  6. #6
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Citation Envoyé par GyZmoO Voir le message
    ...
    Le but de notre requête est de récupérer pour chaque venue, le premier passage (au sens chronologique) ainsi que le dernier.
    Pour le moment notre requête qui récupère le premier passage ressemble à ça :

    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
     
    SELECT
                    PASSAGE.ID_VENU as idVenue,
                    PASSAGE.DATE_DEBUT as dateDebut
                FROM
                    PASSAGE 
                INNER JOIN
                    (
                        SELECT
                            PASSAGE.ID_VENU,
                            MIN(PASSAGE.DATE_DEBUT) as mini 
                        FROM
                            PASSAGE 
                        GROUP BY
                            PASSAGE.ID_VENU
                    ) INNERTMP 
                        ON INNERTMP.ID_VENU = PASSAGE.ID_VENU 
                        AND INNERTMP.mini  = PASSAGE.DATE_DEBUT
    ...
    Je n'arrive pas à comprendre votre requête. La requête intérieure, celle qui a le group by, vous donne déjà la réponse; pourquoi faite vous alors une jointure avec la table passage ?

Discussions similaires

  1. [2.x] requête sql, problème performance
    Par SuperArbre dans le forum Symfony
    Réponses: 3
    Dernier message: 14/01/2014, 08h59
  2. Problème performance sous requête MySQL
    Par Razielwar dans le forum Requêtes
    Réponses: 17
    Dernier message: 23/02/2012, 12h11
  3. [Requête]Problème de moyenne
    Par Angath dans le forum Langage SQL
    Réponses: 7
    Dernier message: 05/10/2005, 23h58
  4. Problème performance SELECT avec jointure
    Par Netgamer dans le forum Requêtes
    Réponses: 7
    Dernier message: 05/08/2005, 10h20
  5. [Requête] Problème avec fonction "DATE_FORMAT()"
    Par sekiryou dans le forum Requêtes
    Réponses: 4
    Dernier message: 11/01/2005, 21h52

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