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 :

Faire un distinct optimisé [11g]


Sujet :

SQL Oracle

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Par défaut Faire un distinct optimisé
    Bonjour,

    La requête ci-dessous s'exécute correctement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT T1.ID,
           T1.ID,
           T2.TAP_ID,
           V1.CH1,
           FONCTION1(T1.ID) AS CH2,
           FONCTION2(T1.ID) AS CH3,
           FONCTION3(T1.ID) AS CH4
      FROM TABLE1 T1
    	JOIN VUE1 V1 ON T1.V1_ID = V1.ID
    	JOIN TABLE2 T2 ON T1.ID = T2.T1_ID;
    Mais, lorsque j'ajoute un distinct dans la requête au début du select, le temps d'exécution devient très lent.

    J'aurais voulu savoir comment faire pour optimiser la requête avec le distinct?

    Merci.

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 133
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    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 133
    Par défaut
    Pour effectuer un DISTINCT, le SGBD va commencer par trier le résultat de la requête.
    Qu'est-ce qui se passe si tu ajoutes un ORDER BY sur toutes les colonnes de la requête ?
    Que font les fonctions que tu n'as pas décrites ?
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Par défaut
    Ce sont des fonctions qui permettent de récupérer des valeurs en fonction d'un paramètre défini.

    En effet, en supprimant les fonctions dans le select, on a un meilleur temps d'exécution.

    Est ce que je suis obligé de revoir ces fonctions ou il y a une autre solution. Car, comme je l'ai dit, sans le distinct , la requête s'exécute correctement.

  4. #4
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 204
    Par défaut
    J'ai eu exactement le même besoin aujourd'hui. Je n'avais pas de vraie contrainte en performance, et donc j'ai gardé ma version très lente. Mais suite à la lecture de ta question, je viens de tâtonner, pour voir.

    Ma requête renvoie environ 10000 lignes (et 9000 après distinct ou en fait Group by dans mon cas).
    Sans le distinct, ma requête est quasi instantanée.
    Mais c'est une illusion d'optique.
    Quand je lance ma requête (SQL Developper), elle me renvoie quasi instantanément mes 50 premières lignes. Mais si je lui demande d'afficher les 50 suivantes, etc etc, le temps d'exécution augmente. Et en fait, pour m'afficher les 10000 lignes, il faut une minute.
    Et quand j'ajoute le DISTINCT ou le GROUP BY, il faut toujours une minute.
    Ma fonction a été écrite avec les pieds. C'est elle qui est en cause, et pas le DISTINCT.

    J'ai tenté des trucs comme ci-dessous, mais ça ne change rien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    With X  as 
    (select /*+ materialize */ 
           T1.ID,
           T2.TAP_ID,
           V1.CH1,
           FONCTION1(T1.ID) AS CH2,
           FONCTION2(T1.ID) AS CH3,
           FONCTION3(T1.ID) AS CH4
      FROM TABLE1 T1
    	JOIN VUE1 V1 ON T1.V1_ID = V1.ID
    	JOIN TABLE2 T2 ON T1.ID = T2.T1_ID
    )
    select distinct id, tap_id, ch1, ch2, ch3, ch4 from X
    Mais dans mon cas, ça n'améliore rien.

    Peut-être que dans ton cas, le problème est un peu différent, et cette astuce fonctionnera ?

  5. #5
    Membre Expert
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Février 2012
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Distribution

    Informations forums :
    Inscription : Février 2012
    Messages : 652
    Par défaut
    Et est-ce possible de remplacer les fonctions par des sous-requêtes, à tout hasard ?

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 995
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 995
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par al1_24 Voir le message
    Pour effectuer un DISTINCT, le SGBD va commencer par trier le résultat de la requête.
    Bien présomptueux et généralement faux ! En effet un moyen de faire un DISTINCT complexe est soiuvent d'utiliser un hachage....

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Par défaut
    Citation Envoyé par tbc92 Voir le message
    J'ai eu exactement le même besoin aujourd'hui. Je n'avais pas de vraie contrainte en performance, et donc j'ai gardé ma version très lente. Mais suite à la lecture de ta question, je viens de tâtonner, pour voir.

    Ma requête renvoie environ 10000 lignes (et 9000 après distinct ou en fait Group by dans mon cas).
    Sans le distinct, ma requête est quasi instantanée.
    Mais c'est une illusion d'optique.
    Quand je lance ma requête (SQL Developper), elle me renvoie quasi instantanément mes 50 premières lignes. Mais si je lui demande d'afficher les 50 suivantes, etc etc, le temps d'exécution augmente. Et en fait, pour m'afficher les 10000 lignes, il faut une minute.
    Et quand j'ajoute le DISTINCT ou le GROUP BY, il faut toujours une minute.
    Ma fonction a été écrite avec les pieds. C'est elle qui est en cause, et pas le DISTINCT.

    J'ai tenté des trucs comme ci-dessous, mais ça ne change rien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    With X  as 
    (select /*+ materialize */ 
           T1.ID,
           T2.TAP_ID,
           V1.CH1,
           FONCTION1(T1.ID) AS CH2,
           FONCTION2(T1.ID) AS CH3,
           FONCTION3(T1.ID) AS CH4
      FROM TABLE1 T1
    	JOIN VUE1 V1 ON T1.V1_ID = V1.ID
    	JOIN TABLE2 T2 ON T1.ID = T2.T1_ID
    )
    select distinct id, tap_id, ch1, ch2, ch3, ch4 from X
    Mais dans mon cas, ça n'améliore rien.

    Peut-être que dans ton cas, le problème est un peu différent, et cette astuce fonctionnera ?
    Merci pour ta proposition mais ça ne fonctionne pas et j'ai l'impression c'est aussi long ou peut être plus.

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2017
    Messages
    176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2017
    Messages : 176
    Par défaut
    Une solution?

    Hormis ça est ce que je peux modifier le nom d'un champs dans la requête que j'ai fournie car j'aimerais pas qu'elle apparaisse dans la discussion.

  9. #9
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 952
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 952
    Par défaut
    Combien de ligne la requête renvoie-t-elle et combien avec le DISTINCT ?

    Dans la requête T1 est jointe à V1 et à T2.
    Il semble que la jointure vers V1 ne soit pas de cardinalité 1..1 => plus de ligne dans le résultat de T1 JOIN V1 que dans T1 seul, est ce bien le cas ?
    Et avec T2, quelle est la cardinalité de la jointure ?

    Vous générez un produit cartésien entre V1 et T2, d'où le souhait d'utiliser le DISTINCT.

    Quelle est le code de la vue V1 ? Les critères de jointures sont ils suffisant ?


    Afin de faire un peu moins de travail en profitant du cache de sous-requête vous pouvez réécrire la requête comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT T1.ID,
           T1.ID,
           T2.TAP_ID,
           V1.CH1,
           (select FONCTION1(T1.ID) from dual) AS CH2,
           (select FONCTION2(T1.ID) from dual) AS CH3,
           (select FONCTION3(T1.ID) from dual) AS CH4
      FROM TABLE1 T1
    	JOIN VUE1 V1 ON T1.V1_ID = V1.ID
    	JOIN TABLE2 T2 ON T1.ID = T2.T1_ID;

  10. #10
    Membre Expert

    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
    Par défaut
    Bonjour,

    Est-ce que vous avez essayé de sortir les appels des fonctions du distinct? ainsi vous allez (sans effet de caching) faire 1000 appel en moins aux fonctions. Particulièrement quand je vois qu'elles utilisent des paramètres sur lesquels le distinct est appliqué également. Exemple vite fait :

    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
           ww.ID,
           ww.ID,--??
           ww.TAP_ID,
           ww.CH1,
           (select FONCTION1(T1.ID) from dual )AS CH2,
           (select FONCTION2(T1.ID) from dual) AS CH3,
           (select FONCTION3(T1.ID) from dual) AS CH4
     from 
        (
         select
            distinct
               T1.ID,
               T1.ID, -- pkoi?
               T2.TAP_ID,
               V1.CH1
        FROM TABLE1 T1
    	JOIN VUE1 V1 ON T1.V1_ID = V1.ID
    	JOIN TABLE2 T2 ON T1.ID = T2.T1_ID
        ) ww
    Bien Cordialement
    Mohamed Houri

  11. #11
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 995
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 995
    Billets dans le blog
    6
    Par défaut
    Un SGBDR est optimisé pour effectuer des manipulations ensemblistes sur des jeux de données (dataset). Pour ce faire il optimise au maximum la requête en utilisant, la simplification algébrique, l'optimisation sémantique, le parallélisme, les index et plus généralement l'optimisation statistique en évaluant la cardinalité de chaque opération afin de prendre l'algorithme optimal en fonction du contexte (en estimant le nombre de ligne via des statistiques et le nombre d'octet de chaque ligne via les tables systèmes).

    Tout opération non ensembliste, comme c'est le cas des fonctions, est impossible à optimisé selon ces règles et vous vous retrouvez à lancer n fois la fonction, n étant le nombre de ligne à extraire. Si la fonction utilise une requête qui parcoure de nombreuses lignes (mettons m lignes) alors globalement la requête aura à traiter m x n lignes. Si en plus vous appelez 3 fois la fonction, la requête aura à traiter 3 x m x n lignes...

    Maintenant si vous supprimez toutes vos fonctions et reportez le code de vos fonctions directement dans la requête, l'optimiseur est capable de faire du bon boulot et les temps de réponse seront adéquat...

    Autrement dit, ce que l'on vous a appris àa faire en développement d'IHM en vous demandant de factoriser et d'imbriquer les méthodes et fonctions au niveau du code itératif (java, C++, C#, PHP, Python...), c'est juste l'inverse qu'il faut faire dans le langage SQL si vous voulez des performances...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

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

Discussions similaires

  1. Faire un distinct count suite à plusieurs group by
    Par kevinze1 dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 15/09/2008, 13h23
  2. faire un distinct par jour sur champ contenant un time()
    Par mdr_cedrick dans le forum Langage SQL
    Réponses: 1
    Dernier message: 01/08/2008, 11h10
  3. ne pas faire la distinction entre majuscule et minuscule
    Par Joe Le Mort dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 26/06/2007, 18h15
  4. Réponses: 2
    Dernier message: 22/07/2006, 02h13
  5. [SQL] Faire un Distinct en incluant un champ de type Memo
    Par Pedro dans le forum Bases de données
    Réponses: 30
    Dernier message: 23/03/2006, 19h08

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