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 :

Plusieurs liens sur une même table : problème de performance


Sujet :

SQL Oracle

  1. #1
    Futur Membre du Club
    Inscrit en
    Février 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 14
    Points : 6
    Points
    6
    Par défaut Plusieurs liens sur une même table : problème de performance
    Bonjour,

    Je travaille sur une requête très simple: afficher les champs d'un fichier articles y compris les champs statistiques et ses libellés.

    Les libellés des champs stats sont dans une autre table: je dois donc lire la table statistiques autant de fois qu'il y a de champs de stats dans le fichier article. En l’occurrence: 6

    Nombre de liens (lecture) et performance:
    - 4 liens --> 11 s;
    - 5 liens --> 2 min
    - 6 liens --> time out (10 min)

    Est-ce qu'il y a une façon d'optimiser ma requête ?

    En vous remerciant

  2. #2
    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
    Utiliser des jointures.

  3. #3
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Et fournir la structure des tables !

  4. #4
    Futur Membre du Club
    Inscrit en
    Février 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Merci beaucoup pour vos réponses:

    --> J'ai fait la requête avec des liaisons.
    --> La structure de la clef (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
    21
    22
    23
    24
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_1 ON
    	(APRODDTA___F4101_.IMSRP1 = SUBSTR(PRODCTL_F0005_1.DRKY,-3) AND	PRODCTL_F0005_1.DRSY = '41' AND 	PRODCTL_F0005_1.DRRT = 'S1')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_2 ON
    	(APRODDTA___F4101_.IMSRP2 = SUBSTR(PRODCTL_F0005_2.DRKY,-3) AND	PRODCTL_F0005_2.DRSY = '41' AND 	PRODCTL_F0005_2.DRRT = 'S2')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_3 ON
    	(APRODDTA___F4101_.IMSRP3 = SUBSTR(PRODCTL_F0005_3.DRKY,-3) AND	PRODCTL_F0005_3.DRSY = '41' AND 	PRODCTL_F0005_3.DRRT = 'S3')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_4 ON
    	(APRODDTA___F4101_.IMPRP1 = SUBSTR(PRODCTL_F0005_4.DRKY,-3) AND	PRODCTL_F0005_4.DRSY = '41' AND 	PRODCTL_F0005_4.DRRT = 'P1')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_5 ON
    	(APRODDTA___F4101_.IMPRP2 = SUBSTR(PRODCTL_F0005_5.DRKY,-3) AND	PRODCTL_F0005_5.DRSY = '41' AND 	PRODCTL_F0005_5.DRRT = 'P2')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_6 ON
    	(APRODDTA___F4101_.IMPRP3 = SUBSTR(PRODCTL_F0005_6.DRKY,-3) AND	PRODCTL_F0005_6.DRSY = '41' AND 	PRODCTL_F0005_6.DRRT = 'P3')

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

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Avec un CASE (ou un max(case...)) ça devrait être possible avec une seule jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select ...,
           case when PRODCTL_F0005_1.DRRT = 'S1' then ... end as s1_...
           case when PRODCTL_F0005_1.DRRT = 'S2' then ... end as s2_...
           ...
      from APRODDTA___F4101_
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_1 ON APRODDTA___F4101_.IMSRP1 = SUBSTR(PRODCTL_F0005_1.DRKY,-3)
    where PRODCTL_F0005_1.DRSY = '41' 
      AND PRODCTL_F0005_1.DRRT in ('S1','S2','S3','P1','P2','P3')
    Par ailleurs il sera peut être intéressant de créer un index de fonction sur SUBSTR(PRODCTL.F0005,-3) peut être même couplé à DRSY.

  6. #6
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Si on pouvait avoir la requête complète, ça aiderait à proposer quelque chose. C'est difficile de proposer quoi que ce soit, on ne sait vraiment pas grand chose. Une idée des volumétries en jeu ? Avec un peu de répartition si possible.

    Un peu au pif au vu du peu d'informations, on pourrait tenter quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CREATE INDEX IDX_TEST_PERF ON PRODCTL.F0005 (   SUBSTR(DRKY,-3) , DRSY, DRRT) )
    L'ordre des colonnes pourrait être modifié selon les volumétries. On pourrait aussi ajouter des colonnes à la fin pour éviter les accès à la table. Ou encore ré-écrire la requête en factorisant le parcours de la table, si on connaissait la structure et les contraintes de la table lues beaucoup de fois.

    Mais pour ça il faut plus d'informations !

  7. #7
    Futur Membre du Club
    Inscrit en
    Février 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Merci pour la réponse.
    bonne idée le Case.

  8. #8
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Citation Envoyé par skuatamad Voir le message
    Avec un CASE (ou un max(case...)) ça devrait être possible avec une seule jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select ...,
           case when PRODCTL_F0005_1.DRRT = 'S1' then ... end as s1_...
           case when PRODCTL_F0005_1.DRRT = 'S2' then ... end as s2_...
           ...
      from APRODDTA___F4101_
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_1 ON APRODDTA___F4101_.IMSRP1 = SUBSTR(PRODCTL_F0005_1.DRKY,-3)
    where PRODCTL_F0005_1.DRSY = '41' 
      AND PRODCTL_F0005_1.DRRT in ('S1','S2','S3','P1','P2','P3')
    Par ailleurs il sera peut être intéressant de créer un index de fonction sur SUBSTR(PRODCTL.F0005,-3) peut être même couplé à DRSY.
    Il faut faire plus que cela - un group by au minimum, car les jointures sont cumulatives (il faut donc une ligne avec s1, une ligne avec s2, etc.).

  9. #9
    Futur Membre du Club
    Inscrit en
    Février 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    La volumétrie :
    -Table article (F4101): 2833 enregistrements;
    -Table diverses (F0005): 40542 enregistrements;

    La table des stat (F0005) est, comme souvent, une table fourre-tout, d'ou sa volumétrie délirante.

    La requête complète n'est pas très compliquée; il s'agit d'avoir une liste articles complète sur laquelle s’appuieront d'autres requête (Je travaille avec MyReport)

    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    SSELECT 
    	APRODDTA___F4101_.IMLITM AS Article_ID, 
    	APRODDTA___F4101_.IMDSC1 AS Designation, 
    	APRODDTA___F4101_.IMSRP1 AS Stat_1, 
    	PRODCTL_F0005_1.DRDL01 AS Stat_1_Lib, 
    	APRODDTA___F4101_.IMSRP2 AS Stat_2, 
    	PRODCTL_F0005_2.DRDL01 AS Stat_2_Lib, 
    	APRODDTA___F4101_.IMSRP3 AS Stat_3, 
    	PRODCTL_F0005_3.DRDL01 AS Stat_3_Lib, 
    	APRODDTA___F4101_.IMPRP1 AS Stat_4, 
    	PRODCTL_F0005_4.DRDL01 AS Stat_4_Lib, 
    	APRODDTA___F4101_.IMPRP2 AS Stat_5, 
    	PRODCTL_F0005_5.DRDL01 AS Stat_5_Lib, 
    	APRODDTA___F4101_.IMPRP3 AS Stat_6, 
    	PRODCTL_F0005_6.DRDL01 AS Stat_6_Lib, 
    	APRODDTA___F4101_.IMUOM1 AS UOM
     
    FROM 
    	PRODDTA.F4101	APRODDTA___F4101_
     
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_1 ON
    	(APRODDTA___F4101_.IMSRP1 = SUBSTR(PRODCTL_F0005_1.DRKY,-3) AND	PRODCTL_F0005_1.DRSY = '41' AND 	PRODCTL_F0005_1.DRRT = 'S1')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_2 ON
    	(APRODDTA___F4101_.IMSRP2 = SUBSTR(PRODCTL_F0005_2.DRKY,-3) AND	PRODCTL_F0005_2.DRSY = '41' AND 	PRODCTL_F0005_2.DRRT = 'S2')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_3 ON
    	(APRODDTA___F4101_.IMSRP3 = SUBSTR(PRODCTL_F0005_3.DRKY,-3) AND	PRODCTL_F0005_3.DRSY = '41' AND 	PRODCTL_F0005_3.DRRT = 'S3')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_4 ON
    	(APRODDTA___F4101_.IMPRP1 = SUBSTR(PRODCTL_F0005_4.DRKY,-3) AND	PRODCTL_F0005_4.DRSY = '41' AND 	PRODCTL_F0005_4.DRRT = 'P1')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_5 ON
    	(APRODDTA___F4101_.IMPRP2 = SUBSTR(PRODCTL_F0005_5.DRKY,-3) AND	PRODCTL_F0005_5.DRSY = '41' AND 	PRODCTL_F0005_5.DRRT = 'P2')
     
    INNER JOIN
    	PRODCTL.F0005	PRODCTL_F0005_6 ON
    	(APRODDTA___F4101_.IMPRP3 = SUBSTR(PRODCTL_F0005_6.DRKY,-3) AND	PRODCTL_F0005_6.DRSY = '41' AND 	PRODCTL_F0005_6.DRRT = 'P3')
    Pour finir: je suis contrôleur de gestion. i.e. je n'ai pas de droit pour écrire dans la base oracle et mes connaissance en SQL sont limitées.

  10. #10
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Les volumétries me semblent bien faibles pour déclencher ce genre de comportement ... d'après les préfixes, je vois que les schémas sont différents pour les deux tables. Est-ce que à tout hasard l'une des deux tables serait sur une base distante ? Avec un alias sur une table accédée par DataLink ? Ca pourrait expliquer des lenteurs telles que celles que vous signalez ...

    Sinon, vous pouvez demander la création de l'index suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CREATE INDEX IDX_TEST_PERF ON PRODCTL.F0005 (   DRSY, DRRT, SUBSTR(DRKY,-3) ,  DRDL01  ) )
    Ou encore ré-écrire la requête :
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    WITH libelles AS
    (
    SELECT MAX ( CASE WHEN DRRT = 'S1' THEN DRDL01 END) AS Stat_1_Lib
              ,MAX ( CASE WHEN DRRT = 'S2' THEN DRDL01 END) AS Stat_2_Lib
              ,MAX ( CASE WHEN DRRT = 'S3' THEN DRDL01 END) AS Stat_3_Lib
              ,MAX ( CASE WHEN DRRT = 'S3' THEN DRDL01 END) AS Stat_3_Lib
              ,MAX ( CASE WHEN DRRT = 'P1' THEN DRDL01 END) AS Stat_4_Lib
              ,MAX ( CASE WHEN DRRT = 'P2' THEN DRDL01 END) AS Stat_5_Lib
              ,MAX ( CASE WHEN DRRT = 'P3' THEN DRDL01 END) AS Stat_6_Lib
             ,SUBSTR(DRKY,-3) AS DRKY_LAST_3
      FROM PRODCTL.PRODCTL_F0005
    WHERE DRSY = '41' 
    GROUP BY SUBSTR(DRKY,-3)
    -- note : s'il manque un libelle, la ligne sera quand même retournée
    -- si on veut rajouter le controle que tous les libellés soient présents 
    -- il faut rajouter HAVING count(*) = 6
    )
    SELECT 
    	APRODDTA___F4101_.IMLITM AS Article_ID, 
    	APRODDTA___F4101_.IMDSC1 AS Designation, 
    	APRODDTA___F4101_.IMSRP1 AS Stat_1, 
    	libelles.Stat_1_Lib, 
    	APRODDTA___F4101_.IMSRP2 AS Stat_2, 
    	libelles.Stat_2_Lib, 
    	APRODDTA___F4101_.IMSRP3 AS Stat_3, 
    	libelles.Stat_3_Lib, 
    	APRODDTA___F4101_.IMPRP1 AS Stat_4, 
    	libelles.Stat_4_Lib, 
    	APRODDTA___F4101_.IMPRP2 AS Stat_5, 
    	libelles.Stat_5_Lib, 
    	APRODDTA___F4101_.IMPRP3 AS Stat_6, 
    	libelles.Stat_6_Lib, 
    	APRODDTA___F4101_.IMUOM1 AS UOM
     
    FROM 
    	PRODDTA.F4101	APRODDTA___F4101_
     INNER JOIN libelles 
           ON libelles.DRKY_LAST_3 = APRODDTA___F4101_.IMSRP1
    Note :

  11. #11
    Futur Membre du Club
    Inscrit en
    Février 2008
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Désolé pour ma réponse tardive, je reviens de congés
    Je teste tout ça rapidement; merci !

Discussions similaires

  1. Plusieurs SUM sur une même table
    Par fbms18 dans le forum SQL
    Réponses: 6
    Dernier message: 29/04/2011, 09h45
  2. Réponses: 8
    Dernier message: 03/05/2010, 14h56
  3. Plusieurs trigger sur une même table / Performances
    Par tchoimars dans le forum PL/SQL
    Réponses: 2
    Dernier message: 27/01/2010, 15h58
  4. Suivi de plusieurs plans d'actions sur une même table
    Par Mac_yavel dans le forum Modélisation
    Réponses: 2
    Dernier message: 20/07/2007, 13h44
  5. [MySQL] Plusieurs même requetes sur une même table
    Par bibom dans le forum PHP & Base de données
    Réponses: 14
    Dernier message: 27/07/2006, 12h54

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