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

PL/SQL Oracle Discussion :

DBMS_PARALLEL_EXECUTE.TASK_STATUS = crashed ! si je veux paralléliser une requête


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    GO
    GO est déconnecté
    Membre confirmé Avatar de GO
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 114
    Par défaut DBMS_PARALLEL_EXECUTE.TASK_STATUS = crashed ! si je veux paralléliser une requête
    Bonjour,

    Voilà mon code, j'essaye de paralléliser une requête par ROWID, dans le select, une fonction qui calcule et écrit dans une autre table (tout cela packagé) :

    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
    DECLARE
     
        c_update_statement CONSTANT VARCHAR2 (2000)
        := 'select  PKG_STOCK.so_f_ea_insert_mb_new(ad.adhe_cod_prod, ad.adhe_no_adhes, decode(trunc(sysdate), trunc(last_day(sysdate)), trunc(SYSDATE)
                                                                                                                                      , decode(to_char(sysdate, ''D''), 5, trunc(SYSDATE)
                                                                                                                                                                       , trunc(SYSDATE)))) 
            from  /*+ ROWID (dda) */ ADHESIONS ad
            where ROWID BETWEEN :starting_rowid AND :ending_rowid';
     
        c_task_name   CONSTANT VARCHAR2 (20) := 'Give Raise';
        l_attempts    PLS_INTEGER := 1;
        retries_in    PLS_INTEGER := 2;
        l_d_effet     DATE;
     
    BEGIN   
      BEGIN 
        DBMS_OUTPUT.put_line('[SQL-INFO] Lancement du script');
        DBMS_PARALLEL_EXECUTE.CREATE_TASK (c_task_name);
     
        DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID (task_name => c_task_name
                                 , table_owner => USER
                                 , table_name => 'ADHESIONS'
                                 , by_row => TRUE
                                 , chunk_size => 1000
                                  );

    Mais lorsque j'exécute le suite le statut de la tâche passe en CRASHED !!! et mon job se termine, pouvez-vous m'éclairer sur l'origine du crash et si ma requête initiale est bien implémentée, merci !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DBMS_PARALLEL_EXECUTE.RUN_TASK (task_name => c_task_name
                      , sql_stmt => c_update_statement
                      , language_flag => DBMS_SQL.native
                      , parallel_level => 10
                       );
    Cdlt,

  2. #2
    GO
    GO est déconnecté
    Membre confirmé Avatar de GO
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 114
    Par défaut
    J'ai lu que le hint ROWID était deprecated depuis Oracle 9....

    Donc j'ai remplacé ma requête telle que directement dans le code en supprimant la création et le lancement de TASK via DBMS_PARALLEL_EXECUTE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    BEGIN
          select  /*+ PARALLEL(ADHESIONS, 16) */ PKG_STOCK.so_f_ea_insert_mb_new(ad.adhe_cod_prod, ad.adhe_no_adhes, decode(trunc(sysdate), trunc(last_day(sysdate)), trunc(SYSDATE)
                                                                                                                                      , decode(to_char(sysdate, 'D'), 5, trunc(SYSDATE)
                                                                                                                                                                       , trunc(SYSDATE)))) 
          BULK COLLECT INTO l_tab_result
          from   ADHESIONS ad;
        EXCEPTION
          WHEN OTHERS THEN
            DBMS_OUTPUT.put_line('[SQL-INFO] Erreur de parallélisation du script');
        END;
    Mais j'ai l'impression que ça ne parallélise pas à l'exécution, dois-je conserver DBMS_PARALLEL_EXECUTE.RUNTASK dans mon code... et comment l'implémenter avec le hint /* +PARALLEL */ ??

  3. #3
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    De toutes façons votre hint ROWID étant placé au niveau du FROM est gentillement ignoré par l'optimiseur.
    Les hints comme vous l'avez fait dans la seconde requête se placent après le SELECT.

    Par contre le dernier argument de votre fonction mérite d'être encadré
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    decode(trunc(sysdate), trunc(last_day(sysdate)), trunc(SYSDATE), decode(to_char(sysdate, 'D'), 5, trunc(SYSDATE), trunc(SYSDATE)))
    C'est strictement identique à trunc(sysdate).

    Sinon, le parallélisme de PARALLEL et de DBMS_PARALLEL_EXECUTE n'ont rien à voir.
    Le premier se fait sur des requêtes unitaires, le second génère une file de traitement et en exécute X en parallèle, dès qu'un est terminé il pioche le suivant.

    Donc... que voulez-vous faire ?

  4. #4
    GO
    GO est déconnecté
    Membre confirmé Avatar de GO
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 114
    Par défaut
    Merci pour votre réponse, effectivement en date d'aujourd'hui le dernier paramètre = trunc(sysdate) qui est par défaut pour pourvoir de lancer tout les jours pour les besoins de mes tests sinon cela se fera un vendredi ou un dernier jour du mois (en enlevant le dernier argument ou en ne renvoyant une date invalide pour court-circuiter le traitement et le gérant dans la fonction appelée).

    En fait j'ai placé la fonction dans le select car c'est elle le coeur du traitement pour chaque adhésion elle calcule des valeurs qui sont insérées dans une autre table j'ai d'ailleurs du mettre une session autonome dans la fonction appelée pour pouvoir écrire dans le select...

    Si je fais bêtement ce traitement adhésion par adhésion cela met près de 10 heures (il y a 280000 adhésions), l'idée est de paralléliser les traitements en lançant plusieurs simultanément (qui appelle la fonction avec des n° d'adhésions différentes) tout cela par pool de 1000 ou 10000 adhésions par exemple.

    Ma première idée "deprecated" sur la V12c d'Oracle semble posait problème, alors dans ma seconde idée c'était de découper la requête en bloc d'adhésions - en utilisant le hint parallel et/ou parallel_index - et les lancer simultanément aussi via la requête et non plus passer par des TASK/CHUNK, ceci semble créer plusieurs instances de mon traitement sur le serveur mais les résultats ne sont pas meilleurs que si j'utilise uniquement l'index principal de ma table ADHESIONS...

    MAis actuellement je pense revenir sur ma première idée en enlevant le hint ROWID et mettre un autre hint (parallel ??? ou parallel_index???) ou pas de hint mais en lançant des tâches simultanées via DBMS_PARALLEL_EXECUTE mais comment effectuer le découpage alors en lot d'adhésions ??

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

    Informations forums :
    Inscription : Août 2008
    Messages : 2 953
    Par défaut
    Citation Envoyé par GO Voir le message
    sinon cela se fera un vendredi
    Attention, to_char(sysdate, 'D') est dépendant du paramètre de session NLS_TERRITORY, assurez-vous donc que le traitement s'exécute bien en NLS_TERRITORY=FRANCE, avec un alter session par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER session SET nls_territory = 'FRANCE';
    Citation Envoyé par GO Voir le message
    En fait j'ai placé la fonction dans le select car c'est elle le coeur du traitement pour chaque adhésion elle calcule des valeurs qui sont insérées dans une autre table j'ai d'ailleurs du mettre une session autonome dans la fonction appelée pour pouvoir écrire dans le select...
    Ça c'est une très mauvais idée, transformer votre fonction en procédure, pas besoin alors de transaction autonome, ni de SELECT

    Et inspirez-vous de cet exemple pour configurer l'appel à la procédure :
    DBMS_PARALLEL_EXECUTE
    A partir de :
    The following example shows the processing of a workload chunked by a number column. Notice that the workload is actually a stored procedure in this case.
    [EDIT] Et n'utilisez pas WHEN OTHERS comme vous l'avez montré ci-dessus :
    http://www.orafaq.com/wiki/WHEN_OTHERS

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Il faudrait voir ce que fait votre fonction, de manière assez générale la meilleure optimisation c'est de faire un traitement ou une succession de traitements ensemblistes, si c'est possible bien entendu.
    Donc si votre fonction ne fait pas 10.000 lignes de codes et que vous pouvez la publier n'hésitez pas.

  7. #7
    GO
    GO est déconnecté
    Membre confirmé Avatar de GO
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 114
    Par défaut
    Merci
    skuatamad
    , ça a vraiment bien avancé, ça parallélise et c'est en train de tourner, j'espère qu'il y aura un gain après je peux changer le chunk_size et le parallel_level pour adapter j'ai commencé par 10000 et 16.

    Par contre il fallait bien mettre autonomous transaction dans ma nouvelle procédure (:id_start, :id_end) sinon rien ne se commite !!! et c'est vérifié.

    Et je suis bien en NLS_TERRITORY=FRANCE.

    Waldar
    pas 10000 lignes mais pas loin puis c'est du code protégé dans le cadre pro, donc désolé.

    Encore merci


Discussions similaires

  1. [MPI] Paralléliser une application en C++
    Par fatjoe dans le forum Programmation parallèle, calcul scientifique et de haute performance (HPC)
    Réponses: 18
    Dernier message: 29/08/2019, 15h20
  2. Je veux deployer une application dans TOMCAT mais..
    Par zambizi dans le forum Tomcat et TomEE
    Réponses: 2
    Dernier message: 09/12/2007, 14h11
  3. [MASM32] Je veux faire une dll "résultat = cos (degrés)"
    Par papiX dans le forum x86 32-bits / 64-bits
    Réponses: 2
    Dernier message: 07/04/2007, 16h34
  4. Problème lorsque je veux changer une session
    Par mouloudéen dans le forum Windows XP
    Réponses: 3
    Dernier message: 16/12/2006, 13h51
  5. erreur quand je veux remplir une CList :
    Par stof dans le forum MFC
    Réponses: 10
    Dernier message: 03/02/2005, 16h18

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