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

Administration Oracle Discussion :

Optimisation requetes SQL


Sujet :

Administration Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Inscrit en
    Mai 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 10
    Par défaut Optimisation requetes SQL
    Bonjour,
    Je suis aujourd'hui confronté à des pb de temps de réponses sur certaines requetes, malgré la pose d'index, de tables en mémoire, etc...
    Voici le code d'une des requetes :
    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
    SELECT
      lower(SUPRALOCAL.REF),
      sum(decode(DO0.VAR13,'Gagnée',1,0)),
      XORGALIEN_Supra.ID_PC,
      sum(decode(DO0.ETAT,'Clôturée', 1,0)),
      sum(decode(DO0.ETAT,'En cours', 1,0))
    FROM
      XORGALIEN  XORGALIEN_Supra,
      DO0,
      SO0,
      AR0,
      AR0  SUPRALOCAL
    WHERE
      ( SO0.AR0_NRID=AR0.NRID  )
      AND  ( SUPRALOCAL.NRID=AR0.AR0_SUPRA_NRID  )
      AND  ( XORGALIEN_Supra.CODE_INSEE=SUPRALOCAL.CDE_TVA  )
      AND  ( SO0.NRID=DO0.SO0_NRID  )
      AND  ( SO0.TYPE='Particulier'  )
      AND  ( DO0.DAT1 >= to_date('01/01/'||TO_CHAR(sysdate,'YYYY'),'DD/MM/YYYY')  )
      AND  (
      ( lower(SUPRALOCAL.CATEGORIE)='extension'  )
      AND  ( SUPRALOCAL.nrid in (select ar0_supra_nrid from ar0
                             where ar0_supra_nrid is not null)  )
      AND  trunc(DO0.DAT1)  >=  '01-07-2002 00:00:00'
      AND  SO0.TYPE  =  'Particulier'
      )
    GROUP BY
      lower(SUPRALOCAL.REF), 
      XORGALIEN_Supra.ID_PC
    Cette requête va mettre jusqu'à 40MN !!!!
    Voici pour info l'explain PLAN :
    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 STATEMENT Optimizer Mode=CHOOSE 1  	10835
    SORT GROUP BY		1  	114  	10835
    NESTED LOOPS		1  	114  	10821
    HASH JOIN		                1  	106 	10817
    NESTED LOOPS		19  	1 K	10021
    NESTED LOOPS		1 K	87 K	7497
    NESTED LOOPS		1 K	73 K	4973
    TABLE ACCESS FULL	DO0	1 K	37 K	2445
    TABLE ACCESS BY INDEX ROWID SO0	23 M	671 M	2
    INDEX UNIQUE SCAN	PK_SO0	23 M	 	1
    TABLE ACCESS BY INDEX ROWID AR0	26 M	280 M        2
    INDEX UNIQUE SCAN	PK_AR0	26 M	 	1
    TABLE ACCESS BY INDEX ROWID AR0	26 K	855 K	2
    INDEX UNIQUE SCAN	PK_AR0	26 K	 	1
    VIEW	VW_NSO_1	18 K	36 K	795
    SORT UNIQUE		18 K	36 K	795
    INDEX FAST FULL SCAN IDX_AR0_AR0_SUPRA_NRID	396 K	774 K	124  	 	
    TABLE ACCESS BY INDEX ROWID XORGALIEN	36 K	285 K	4  	 	      	             
    INDEX RANGE SCAN	SEL_XORGALIEN	36 K	 	2

    En résumé, la requête passe par les index (pour les grosses tables 31M de lignes), et fait des Full Scan sur de petites tables.
    Comment puis je optimiser cette requête ?
    merci d'avance pour vos solutions.

  2. #2
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    est-ce que tu as un index sur DO0.DAT1 ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SUPRALOCAL.nrid in (select ar0_supra_nrid from ar0 
                             where ar0_supra_nrid is not null
    Pourquoi tu fais ça alors que ar0 est déjà dans le FROM ?

    Sinon, la requête parait bonne, le plan d'exécution est correct... t'as du volume dans les tables ?

  3. #3
    Expert Oracle confirmé

    Homme Profil pro
    Consultant Big Data
    Inscrit en
    Mars 2003
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Consultant Big Data
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2003
    Messages : 448
    Par défaut
    Bonjour,


    A la place de to_date('01/01/'||TO_CHAR(sysdate,'YYYY'),'DD/MM/YYYY'), il suffit de mettre trunc (sysdate, 'YYYY').

    Ensuite, à la place de trunc(DO0.DAT1) >= '01-07-2002 00:00:00' ,
    il faut mettre DO0.DAT1 >= to_date ('01-07-2002 00:00:00', 'DD-MM-YYYY HH24:MI:SS' )

    Sinon, je ne comprends pas pourquoi tu compares DO0.DAT1 2 fois (une fois au 1er juillet 2002, et une autre fois à l'année en cours). Mais peut-être que tu as une bonne raison.

    Et puis, sauf erreur de ma part, le test sur SO0.TYPE = 'Particulier' est fait 2 fois (à moins que je me sois perdu dans le niveau de parenthèses).

  4. #4
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    lower(SUPRALOCAL.CATEGORIE)='extension'
    êtes-vous obligé d'utiliser la fonction Lower() ?

  5. #5
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    on va le démoraliser le pauvre

  6. #6
    Membre habitué
    Inscrit en
    Mai 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 10
    Par défaut
    Citation Envoyé par SheikYerbouti
    lower(SUPRALOCAL.CATEGORIE)='extension'
    êtes-vous obligé d'utiliser la fonction Lower() ?
    Les index sont de types "lower(SUPRALOCAL.CATEGORIE)" par rapport au fait qu'il peut avoit "Extension", "extension" ou encore "EXTENSION".

  7. #7
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Citation Envoyé par joel90
    Citation Envoyé par SheikYerbouti
    lower(SUPRALOCAL.CATEGORIE)='extension'
    êtes-vous obligé d'utiliser la fonction Lower() ?
    Les index sont de types "lower(SUPRALOCAL.CATEGORIE)" par rapport au fait qu'il peut avoit "Extension", "extension" ou encore "EXTENSION".
    Ok, ça marche.

  8. #8
    Membre habitué
    Inscrit en
    Mai 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 10
    Par défaut
    Citation Envoyé par orafrance
    est-ce que tu as un index sur DO0.DAT1 ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SUPRALOCAL.nrid in (select ar0_supra_nrid from ar0 
                             where ar0_supra_nrid is not null
    Pourquoi tu fais ça alors que ar0 est déjà dans le FROM ?

    Sinon, la requête parait bonne, le plan d'exécution est correct... t'as du volume dans les tables ?
    1 - il n'y a pas d'index sur DO0.DAT1

    2 - Fonctionnellement, il faut que je récupére avec cette sous requête un sous ensemble de AR0 pour par la suite le comparer dans mon IN. A ce propos, j'ai modifié le IN (SELECT ar0_supra..... par un IN (SELECT DISTINCT ar0_supra..... Ou encore, j'ai pu lire ici et là dans le forum qu'il vallait mieux remplacer un IN par un EXIST (plus performant ?)
    la requête deviendrait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ( lower(SUPRALOCAL.CATEGORIE)='extension'  )
      AND	exists (select 'x' from ar0
                             where ar0_supra_nrid is not null and SUPRALOCAL.nrid = ar0.ar0_supra_nrid)
    3 - Pour la volumétrie :
    XORGALIEN = 36 000 lignes
    DO0 = 500 000 lignes
    SO0 = 31M de lignes
    AR0 = 26M de lignes

  9. #9
    Membre habitué
    Inscrit en
    Mai 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 10
    Par défaut
    Citation Envoyé par rouardg
    Bonjour,


    A la place de to_date('01/01/'||TO_CHAR(sysdate,'YYYY'),'DD/MM/YYYY'), il suffit de mettre trunc (sysdate, 'YYYY').

    Ensuite, à la place de trunc(DO0.DAT1) >= '01-07-2002 00:00:00' ,
    il faut mettre DO0.DAT1 >= to_date ('01-07-2002 00:00:00', 'DD-MM-YYYY HH24:MI:SS' )

    Sinon, je ne comprends pas pourquoi tu compares DO0.DAT1 2 fois (une fois au 1er juillet 2002, et une autre fois à l'année en cours). Mais peut-être que tu as une bonne raison.

    Et puis, sauf erreur de ma part, le test sur SO0.TYPE = 'Particulier' est fait 2 fois (à moins que je me sois perdu dans le niveau de parenthèses).
    Pour dire vrai, c'est une requête qui est récupéré d'un SQL BusinessObjects (BO). On a bien SO0.TYPE = 'Particulier' 2 fois dans la requête inutiliement.

  10. #10
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    31 et 26M de lignes ça commence à faire pas mal... peut-être qu'un index partitionnée sur ces 2 tables arrangerait grandement les choses

  11. #11
    Membre habitué
    Inscrit en
    Mai 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 10
    Par défaut
    Citation Envoyé par orafrance
    31 et 26M de lignes ça commence à faire pas mal... peut-être qu'un index partitionnée sur ces 2 tables arrangerait grandement les choses
    Partitionner les tables avec des index partitionnées serait effectivment une bonne idée, mais dans le contexte actuel, on attaque une base de production, et malheureusement pas un DataWarehouse (ou DataMart), la seule action que l'on peut faire, est d'ajouter des index (en prennant soin de ne pas perdre de perfs, pour les MAJ) ou encore d'optimiser le code SQL. Mais notre champ d'action est trés restreint....

  12. #12
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    Tu peux créer un index partitionné sur une table non-partitionnée, ça marche aussi bien

    La seule contrainte c'est que tu es limité aux partitions par RANGE

  13. #13
    Membre émérite
    Inscrit en
    Décembre 2003
    Messages
    493
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 493
    Par défaut
    y a t'il dans ce cas, un gain de perf si la table n'est pas partitionnée?

  14. #14
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    Oui ça peut être particulièrement intéressant

  15. #15
    Membre habitué
    Inscrit en
    Mai 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 10
    Par défaut
    En ouvrant bien les yeux , on fini par trouver énormément d'informations sur ce forum.
    J'ai pu résoudre bon nombre de mes pb avec les indications ou les résolutions trouvées sur ce forum.
    Bravo à tous ceux qui participent activement à faire vivre ce forum, et merci à ceux qui apportent leurs connaisances. 8) 8)

  16. #16
    Expert confirmé
    Avatar de SheikYerbouti
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    6 760
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 6 760
    Par défaut
    Ben, n'hésitez pas à en faire la pub !

  17. #17
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    Citation Envoyé par joel90
    En ouvrant bien les yeux , on fini par trouver énormément d'informations sur ce forum.
    J'ai pu résoudre bon nombre de mes pb avec les indications ou les résolutions trouvées sur ce forum.
    Bravo à tous ceux qui participent activement à faire vivre ce forum, et merci à ceux qui apportent leurs connaisances. 8) 8)
    Content qu'on puisse t'aider

    Pourrais tu indiquer la solution que tu as retenue finalement ?

  18. #18
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Par défaut
    Et le gain de perf, tous les utilisateurs de SELLIGENT seront contents

  19. #19
    Membre habitué
    Inscrit en
    Mai 2004
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 10
    Par défaut
    Citation Envoyé par orafrance
    Content qu'on puisse t'aider

    Pourrais tu indiquer la solution que tu as retenue finalement ?
    Comme je l'expliquais, ma marche de manoeuvre est plutôt restreinte, les solutions trouvées ont été de revoir le code SQL afin d'y apporter des améliorations.
    La solution idéale, étant de pouvoir dénormaliser le modéle, et d'éviter des jointures multiples sur les grosses tables, ça c'est pour les utilisateurs de SELLIGENT.
    Autrement, au niveau du code :
    * monter en mémoire les petites tables trés souvent utilisées (XORGALIEN, XORGADEL),
    * remplacer les IN par des EXIST (essayé d'éviter les IN),
    * supprimer les abérations du code (SO0.TYPE = 'Particulier', présent 2 fois, etc...).
    Les temps de réponses sur certaines requêtes : divisés par 2.

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

Discussions similaires

  1. Optimisation requete SQL - exo
    Par Margatthieu dans le forum Langage SQL
    Réponses: 1
    Dernier message: 28/04/2008, 08h54
  2. Optimisation requete SQL ,plusieurs jointure ?
    Par mamiberkof dans le forum Langage SQL
    Réponses: 1
    Dernier message: 22/02/2008, 16h39
  3. optimisation requete SQL
    Par lepierot dans le forum SQL
    Réponses: 20
    Dernier message: 13/09/2007, 15h47
  4. Optimisation requete SQL
    Par compu dans le forum Requêtes
    Réponses: 3
    Dernier message: 07/07/2006, 09h23
  5. [PL/SQL] Optimisation requete SQL
    Par CDRIK dans le forum Langage SQL
    Réponses: 3
    Dernier message: 14/10/2004, 09h52

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