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

Oracle Discussion :

Optimisation requête et trace


Sujet :

Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 39
    Par défaut Optimisation requête et trace
    Bonjour,

    je suis sous oracle 9.2.0.4. Depuis plusieurs jours nous avons un batch qui "a priori" tourne mais ne se termine pas. Il reste bloqué sur une procédure stockée :
    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
     
    PROCEDURE X
      (
        p_dt_min IN DATE,
        p_dt_max IN DATE
      ) IS
     
        -- Curseur de recherche des operations dans la table de reporting
        CURSOR c1 IS
          SELECT DISTINCT a
            FROM tab1
           ORDER BY a;
     
        -- Curseur de recherche des UO traitantes dans la table de reporting
        CURSOR c2(p_a tab3.a%TYPE) IS
          SELECT DISTINCT b
            FROM tab1
           WHERE a = p_a;
     
        -- Curseur de recherche des UO traitee dans la table de reporting
        CURSOR c3(p_a tab3.a%TYPE, p_b tab3.b%TYPE) IS
          SELECT DISTINCT c
            FROM tab1
           WHERE a = p_a
             AND b = p_b;
     
        rec1 c1%ROWTYPE;
        rec2 c2%ROWTYPE;
        rec3 c3%ROWTYPE;
     
     
     
      BEGIN
     
        -- Vidage de la table temporaire de calcul des moyennes mobiles tab2
        truncate_table('tab2');
        -- Suppression des index de la table tab2
        drop_table_index('index_tab2');
     
        -- Boucle sur le colonne a
        FOR rec1 IN c1
        LOOP
     
          -- Boucle sur colonne b
          FOR rec2 IN c2(rec1.a)
          LOOP
     
            -- Boucle sur colonne c
            FOR rec3 IN c3(rec1.a, rec2.b)
            LOOP
     
              INSERT INTO tab2
                (date_a
                ,b
                ,a
                ,c
                ,d_mym
                ,e_mym
                ,f_mym
                ,g_mym
                ,h_mym
                ,i_mym
                ,j_mym
                ,k_mym
                ,l_mym
                ,m_mym)
                SELECT date_a,
                       b,
                       a,
                       c,
                       AVG(SUM(d)) over(ORDER BY date_a rows cst_nbmm preceding) AS em,
                       AVG(SUM(e)) over(ORDER BY date_a rows cst_nbmm preceding) AS sm,
                       AVG(SUM(d - e)) over(ORDER BY date_a rows cst_nbmm preceding) AS dm,
                       AVG(SUM(g)) over(ORDER BY date_a rows cst_nbmm preceding) AS debm,
                       AVG(SUM(h)) over(ORDER BY date_a rows cst_nbmm preceding) AS finm,
                       AVG(SUM(d * nvl(n, 0))) over(ORDER BY date_a rows cst_nbmm preceding) AS uem,
                       AVG(SUM(e * nvl(o, 0))) over(ORDER BY date_a rows cst_nbmm preceding) AS usm,
                       AVG(SUM((d - e) * nvl(p, 0))) over(ORDER BY date_a rows cst_nbmm preceding) AS udm,
                       AVG(SUM(g * nvl(p, 0))) over(ORDER BY date_a rows cst_nbmm preceding) AS udebm,
                       AVG(SUM(h * nvl(p, 0))) over(ORDER BY date_a rows cst_nbmm preceding) AS ufinm
                  FROM tab3 t
                 WHERE a = rec1.a
                   AND b = rec2.b
                   AND nvl(c, ' ') = nvl(rec3.c, ' ')
                   AND date_a >= p_dt_min
                   AND date_a <= p_dt_max
                 GROUP BY date_a,
                          b,
                          a,
                          c;
     
     
            END LOOP;
     
            COMMIT;
     
          END LOOP;
     
        END LOOP;
     
     
        -- Creation de l'index index_tab2 = a, b, c, date_a sur la table tab2
        create_table_index('index_tab2',
                           'tab2',
                           'a,b,c,date_a');
     
      EXCEPTION
        WHEN OTHERS THEN
          lblmsg := 'ERREUR ORACLE : ' || to_char(SQLCODE) || ' : ' || SQLERRM;
          --ecriture message d erreur
          RAISE;
     
      END X;
    J'ai demandé un plan d'éxecution à la dba et voilà ce qu'elle me transmets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    CHILD_NUMBER   ID PARENT OPERATION                           OBJECT_NAME                              FILTER_PREDICATES
    ------------ ---- ------ ----------------------------------- ---------------------------------------- ------------------------------
               0    0        INSERT STATEMENT
                    1      0 WINDOW BUFFER
                    2      1 SORT GROUP BY NOSORT
                    3      2 FILTER                                                                       :B2<=:B1
                    4      3 TABLE ACCESS BY INDEX ROWID         tab3
                    5      4 INDEX RANGE SCAN                    index_tab2                                "a"=:B5 AND "b"=:B4 AND NVL("c",' ')=NVL(:B3,' ')
    Je ne mis connais pas des masses, si ce n'est pas du tout, j'ai lu pas mal de post ce matin ainsi que l'url : http://www.developpez.net/forums/forumdisplay.php?f=42

    Il me semble que le niveau de trace de ce plan ne nous apprends pas grand chose, est ce que je me trompe?

    J'ai demandé le niveau de la trace, j'attends une réponse.

    Pourriez vous me conseiller?

    merci par avance pour tt les réponses

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    354
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 354
    Par défaut
    D'après ce que je vois dans le plan en tant que tel rien d'anormal même si des informations manquent

    Qq points:
    - quels sont les index sur la table et notamment sur les colonnes utilisées dans la clause where
    - Le nombre de lignes de la table tbr001raa
    - L'efficacité de l'index utilisé

    Mais une piste importante consiste à essayer de faire une seule instruction et de se débarasser des curseurs et des boucles.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2005
    Messages : 114
    Par défaut salut
    salut
    j'ai essayé de lire ta procedure c'est pas evident j'ais pas pu detecté qqc qui louche je te propose de diviser ta procedure sur plusieurs scripts afin de voir vraiment ou ca se block c'est comme si tu dbug dans un prog sequential

  4. #4
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 39
    Par défaut
    Citation Envoyé par fontome_ 123 Voir le message
    salut
    j'ai essayé de lire ta procedure c'est pas evident j'ais pas pu detecté qqc qui louche je te propose de diviser ta procedure sur plusieurs scripts afin de voir vraiment ou ca se block c'est comme si tu dbug dans un prog sequential
    Merci pour ta réponse.

    J'ai enlevé pas mal d choses de la procédure, J'a gardé le plus important cad:

    - truncate de la table tab2
    suppression index de la table tab2
    - 3 boucles imbriquées
    - 1 INSERT dans une table tab2 en y mettant des données issues d'un SELECT sur des colonnes d'une table tab3 après avoir fait des moyennes mobiles sur ces colonnes
    - fin des boucles, re-création de l'index de la table tab2

    Voilà, j'espère que cela t'aidera à y voir plus clair.

    merci

  5. #5
    Invité de passage
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 1
    Par défaut Oracle FA
    Bonsoir,

    Je cherche un manuel utilisateur pour Oracle Fa (Fixed Assets), je n'en trouve nulle part,

    Pouvez-vous m'aider,

    Merci

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 50
    Par défaut Un p'tit coup de main
    Citation Envoyé par Tikate Voir le message
    Merci pour ta réponse.

    J'ai enlevé pas mal d choses de la procédure, J'a gardé le plus important cad:

    - truncate de la table tab2
    suppression index de la table tab2
    - 3 boucles imbriquées
    - 1 INSERT dans une table tab2 en y mettant des données issues d'un SELECT sur des colonnes d'une table tab3 après avoir fait des moyennes mobiles sur ces colonnes
    - fin des boucles, re-création de l'index de la table tab2

    Voilà, j'espère que cela t'aidera à y voir plus clair.

    merci
    Bonsoir Tikate,
    vu ce que tu dis, je comprends que tu ais des problèmes de perf. Voici les points que j'ai noté et les questions en suspend :
    - as-tu recalculé les statistiques de la table tab3 après le chargement de ces 2 millions de lignes ?
    - Les 3 boucles imbriquées, ce n'est pas génial (surtout si l'on considère que tu commites trop souvent) (à lire : un article sur asktom.oracle.com)

    Je te conseille de tenter l'approche suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    insert into tab2
    (...)
    select ... from tab3 t3, (select distinct a, b, c from tab1 order by a) t1
    where t3.a = t1.a
       AND t3.b = t1.b
       AND nvl(t3.c, ' ') = nvl(t1.c, ' ')
       AND t3.date_a >= p_dt_min
       AND t3.date_a <= p_dt_max
    GROUP BY t3.date_a,
                   t3.b,
                   t3.a,
                   t3.c;
    Là, tu as supprimé les commit trop nombreux, tes 3 curseurs, les 3 boucles imbriquées. (un seul commit)

    - la comparaison
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nvl(t3.c, ' ') = nvl(t1.c, ' ')
    n'est pas super performante, je te conseille de décider d'une valeur (exemple : 'NULL') afin que les colonnes
    tab3.c et tab1.c soient not nullable ainsi tes index sur tab3 (date_a, a, b, c) et sur tab1 (a, b, c) seront plus sélectifs et donc plus performants MAIS pour 2 millions de lignes, je préfèrerai un FULL table scan dans le plan d'exécution de tab3 et de tab1.

    Bon courage !

  7. #7
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 39
    Par défaut
    Citation Envoyé par wondersonic Voir le message
    Bonsoir Tikate,
    vu ce que tu dis, je comprends que tu ais des problèmes de perf. Voici les points que j'ai noté et les questions en suspend :
    - as-tu recalculé les statistiques de la table tab3 après le chargement de ces 2 millions de lignes ?
    - Les 3 boucles imbriquées, ce n'est pas génial (surtout si l'on considère que tu commites trop souvent) (à lire : un article sur asktom.oracle.com)

    Je te conseille de tenter l'approche suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    insert into tab2
    (...)
    select ... from tab3 t3, (select distinct a, b, c from tab1 order by a) t1
    where t3.a = t1.a
       AND t3.b = t1.b
       AND nvl(t3.c, ' ') = nvl(t1.c, ' ')
       AND t3.date_a >= p_dt_min
       AND t3.date_a <= p_dt_max
    GROUP BY t3.date_a,
                   t3.b,
                   t3.a,
                   t3.c;
    Là, tu as supprimé les commit trop nombreux, tes 3 curseurs, les 3 boucles imbriquées. (un seul commit)

    - la comparaison
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nvl(t3.c, ' ') = nvl(t1.c, ' ')
    n'est pas super performante, je te conseille de décider d'une valeur (exemple : 'NULL') afin que les colonnes
    tab3.c et tab1.c soient not nullable ainsi tes index sur tab3 (date_a, a, b, c) et sur tab1 (a, b, c) seront plus sélectifs et donc plus performants MAIS pour 2 millions de lignes, je préfèrerai un FULL table scan dans le plan d'exécution de tab3 et de tab1.

    Bon courage !
    Merci bcp pour ta réponse.

    Pour répondre à ta question sur les statistiques. Oui elle sont recalculées après l'insert.

    En ce qui concerne ton dernier conseil. En fait je ne connaissais pas les plans d'exécution avant vendredi. Si j'ai bien compris, pour toi il est préférable que Oracle "balaye" la table tab3, lignes par lignes, c'est bien ça le FULL table scan, au lieu d'un balayage en ce servant du rowid comme c'est le cas TABLE ACCESS BY INDEX ROWID ...?
    Je ne suis pas très forte en optimisation mais ne penses tu pas que scanner une table aussi grosse prendra trop de temps?

    je te remercie
    Tikate

  8. #8
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 39
    Par défaut
    Citation Envoyé par Michel SALAIS Voir le message
    D'après ce que je vois dans le plan en tant que tel rien d'anormal même si des informations manquent

    Qq points:
    - quels sont les index sur la table et notamment sur les colonnes utilisées dans la clause where
    - Le nombre de lignes de la table tbr001raa
    - L'efficacité de l'index utilisé

    Mais une piste importante consiste à essayer de faire une seule instruction et de se débarasser des curseurs et des boucles.
    Merci bcp pour ta réponse.
    - De mémoire (je ne suis plus au bureau) l'index de la table tab3 (j'ai tt renommé et j'ai simplifié la procédure) est :
    date_a, a b, c

    - le dernier batch qui a tourné a limenté quelque chose comme 2 millions de lignes

    - l'efficacité de l'index? c'est 4 colonnes constitue la clef primaire il me semble.

    Sinon, peux tu me donner un exemple qui m'expliquerais comment me débarasser de mes boucles?

    merci

  9. #9
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    354
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 354
    Par défaut
    Citation Envoyé par Tikate Voir le message
    Sinon, peux tu me donner un exemple qui m'expliquerais comment me débarasser de mes boucles?
    En regardant le code nous pouvons enlever les boucles et la requête n'est pratiquement pas changée : Ajouter dans la clause FROM les tables des trois curseurs et ajuster dans la clause where en conséquence.

    Evidemment il faudrait dans ce cas faire attention aux index. Mais le gros problème peut-être va être les segments de rollback et là ça peut partir dans la discussion que j'adore ... Tu fais un commit dans les boucles et ce ne sera pas possible. Pourquoi ce commit a été ajouté?

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2005
    Messages : 114
    Par défaut salut
    j'ai pas vraimenet voulais dire symplifier les termes lol mais plutot ton code le deviser pour que tu puisse voir où ca se plante.
    bon a mon avis la seul solution qui te reste c'est d'enlever les boucles 2 propositions :
    1-ou bien comme a dit salais l'utiliser dans les clause where meme si c'est pas evident a mon avis comme requete car justement les pointeurs sont la pour balayer plusieurs tables;
    2-c'est create table tomporaire que tu crée au besoin pour sauvegarder le resultat de la 1,2.... reherche,et le réutiliser apres par la suite drop.
    chose sur il faut enlever le sboucles imbriqué ca n'a jamais etait un bon exemple ca posait des prob dans les editeurs de compilations dedié a ca,alors qu'oracle n'est pas concu pour ca

  11. #11
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 39
    Par défaut
    Je voulais juste ajouter une chose.

    Ce qui m'ennuie c'est que le batch passait sans problème depuis plusieurs mois malgré sa lenteur. Ce que je n'explique pas c'est pourquoi maintenant celui ci reste bloqué à cette étape (la procédure que j'ai citée)? oracle ne signale aucune erreur et le process unix a toujours l'air de continuer à tourner.

    Y a t'il un moyen dans les traces oracle d'en savoir plus sur ce qui ce passe?

    merci

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 50
    Par défaut
    Citation Envoyé par Tikate Voir le message
    Je voulais juste ajouter une chose.

    Ce qui m'ennuie c'est que le batch passait sans problème depuis plusieurs mois malgré sa lenteur. Ce que je n'explique pas c'est pourquoi maintenant celui ci reste bloqué à cette étape (la procédure que j'ai citée)? oracle ne signale aucune erreur et le process unix a toujours l'air de continuer à tourner.

    Y a t'il un moyen dans les traces oracle d'en savoir plus sur ce qui ce passe?

    merci
    Tu peux utiliser le package PL/SQL dbms_profiler pour savoir d'où vient réellement le problème. (sur un petit jeu de données).

    Sinon, est-ce que la table tab1 a subi un gros chargement de données ?
    Est-ce que tu fais beaucoup de tri sur disque (en gros, as-tu assez de mémoire ? ou est-ce que tu swapes ?)

Discussions similaires

  1. optimisation requête-regroupement info
    Par mariobedard dans le forum Langage SQL
    Réponses: 2
    Dernier message: 29/09/2005, 15h10
  2. Besoin d'aide pour optimiser requête SQL
    Par Keuf95 dans le forum Langage SQL
    Réponses: 10
    Dernier message: 06/09/2005, 16h02
  3. Optimiser requête utilisant NOT IN
    Par Neilos dans le forum Langage SQL
    Réponses: 5
    Dernier message: 11/08/2005, 14h24
  4. optimisation requête
    Par alex2205 dans le forum Décisions SGBD
    Réponses: 5
    Dernier message: 09/02/2005, 14h15
  5. optimisation requête SQL!!! help!!
    Par anathem62 dans le forum Requêtes
    Réponses: 2
    Dernier message: 24/05/2004, 16h26

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