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 :

Procédure stockée lente..lente..lente..


Sujet :

PL/SQL Oracle

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 167
    Points : 112
    Points
    112
    Par défaut Procédure stockée lente..lente..lente..
    J'ai un petit souci avec une procédure stockée que j'ai developpé (assez rapidement mais qui est tout de même censé marché ...) Là voici :

    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
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    CREATE OR REPLACE PROCEDURE IHR.PROCEDURE_INSERT_INTO_ZYAG_Q IS  
     
    CURSOR c_zyag_all IS 
    SELECT * 
    FROM IHR.HRA_ZYAG A
    ORDER BY ZY00_SOCCLE ASC, ZY00_MATCLE ASC, ZYAG_NULIGN ASC, ZYAG_DATDEB ASC;
     
    CUR_ZYAG_ALL c_zyag_all%ROWTYPE;
     
     
    CURSOR c_zyag_q_all IS 
    SELECT * 
    FROM IHR.HRA_ZYAG_Q A
    ORDER BY ZY00_SOCCLE ASC, ZY00_MATCLE ASC, ZYAG_NULIGN ASC, ZYAG_DATDEB ASC;
     
    CUR_ZYAG_Q_ALL c_zyag_q_all%ROWTYPE;
     
     
    CURSOR c_zyag IS 
    SELECT * 
    FROM IHR.HRA_ZYAG A
    WHERE A.ZYAG_PROLON IS NULL OR A.ZYAG_PROLON = ''
    ORDER BY ZY00_SOCCLE ASC, ZY00_MATCLE ASC, ZYAG_NULIGN ASC, ZYAG_DATDEB ASC;
     
    CUR_ZYAG c_zyag%ROWTYPE;
     
     
    CURSOR c_zyag2 IS 
    SELECT * 
    FROM IHR.HRA_ZYAG A
    WHERE A.ZYAG_PROLON = 'X'
    ORDER BY ZY00_SOCCLE ASC, ZY00_MATCLE ASC, ZYAG_NULIGN ASC, ZYAG_DATDEB ASC;
     
    CUR_ZYAG2 c_zyag2%ROWTYPE;
     
     
    BEGIN
       --mise à jour des témoins de prolongation oubliés
       FOR CUR_ZYAG_ALL IN c_zyag_all
       LOOP
          UPDATE IHR.HRA_ZYAG A SET A.ZYAG_PROLON = 'X'
          WHERE A.ZY00_SOCCLE = CUR_ZYAG_ALL.ZY00_SOCCLE
          AND A.ZY00_MATCLE = CUR_ZYAG_ALL.ZY00_MATCLE
          AND A.ZYAG_MOTIFA = CUR_ZYAG_ALL.ZYAG_MOTIFA
          AND A.ZYAG_DATDEB = CUR_ZYAG_ALL.ZYAG_DATFIN + 1
          AND (A.ZYAG_PROLON IS NULL OR A.ZYAG_PROLON = '');
     
          COMMIT;
       END LOOP;
     
       --insertion des enregistrements débutant chaque période d'abscence
       FOR CUR_ZYAG IN c_zyag
       LOOP
          INSERT INTO IHR.HRA_ZYAG_Q
    					(ZY00_SOCCLE,
    					 ZY00_MATCLE,
    					 ZY00_NUDOSS,
    					 ZY00_SOCDOS,
    					 ZD00_CDRG03,
    					 ZD00_CDRG04,
    					 ZYAG_NULIGN,
    					 ZYAG_DATDEB,
    					 ZYAG_MOTIFA,
    					 ZYAG_MOTIFA_S,
    					 ZYAG_DATFIN,
    					 ZYAG_TEMDEB,
    					 ZYAG_TEMFIN,
    					 ZYAG_GESTIO,
    					 ZYAG_PROLON,
    					 ZYAG_NBRPRO,
    					 ZYAG_DTABS01,
    					 ZYAG_MOTAB1,
    					 ZYAG_UNITE1,
    					 ZYAG_TEMTR1,
    					 ZYAG_UNITE2,
    					 ZYAG_TEMTR2,
    					 ZYAG_ELEMAT,
    					 ZYAG_ELEMAT_S,
    					 ZYAG_DATUT1,
    					 ZYAG_DATUT2,
    					 ZYAG_SUITUT,
    					 ZYAG_IDRTST,
    					 ZYAG_IDRTST_S)
    		VALUES (CUR_ZYAG.ZY00_SOCCLE,
    				CUR_ZYAG.ZY00_MATCLE,
    				CUR_ZYAG.ZY00_NUDOSS,
    				CUR_ZYAG.ZY00_SOCDOS,
    				CUR_ZYAG.ZD00_CDRG03,
    				CUR_ZYAG.ZD00_CDRG04,
    				CUR_ZYAG.ZYAG_NULIGN,
    				CUR_ZYAG.ZYAG_DATDEB,
    				CUR_ZYAG.ZYAG_MOTIFA,
    				CUR_ZYAG.ZYAG_MOTIFA_S,
    				CUR_ZYAG.ZYAG_DATFIN,
    				CUR_ZYAG.ZYAG_TEMDEB,
    				CUR_ZYAG.ZYAG_TEMFIN,
    				CUR_ZYAG.ZYAG_GESTIO,
    				CUR_ZYAG.ZYAG_PROLON,
    				0,
    				null,
    				null,
    				CUR_ZYAG.ZYAG_UNITE1,
    				CUR_ZYAG.ZYAG_TEMTR1,
    				CUR_ZYAG.ZYAG_UNITE2,
    				CUR_ZYAG.ZYAG_TEMTR2,
    				CUR_ZYAG.ZYAG_ELEMAT,
    				CUR_ZYAG.ZYAG_ELEMAT_S,
    				CUR_ZYAG.ZYAG_DATUT1,
    				CUR_ZYAG.ZYAG_DATUT2,
    				CUR_ZYAG.ZYAG_SUITUT,
    				CUR_ZYAG.ZYAG_IDRTST,
    				CUR_ZYAG.ZYAG_IDRTST_S);
     
          COMMIT;
       END LOOP;
     
       --mise à jour des dates de fin d'abscence et du nombre de prolongation selon les témoins de prolongation
       FOR CUR_ZYAG2 IN c_zyag2
       LOOP
          UPDATE IHR.HRA_ZYAG_Q SET ZYAG_DATFIN = CUR_ZYAG2.ZYAG_DATFIN , ZYAG_PROLON = ZYAG_PROLON + 1
    	  WHERE ZY00_SOCCLE = CUR_ZYAG2.ZY00_SOCCLE
    	  AND ZY00_MATCLE = CUR_ZYAG2.ZY00_MATCLE
    	  AND ZYAG_MOTIFA = CUR_ZYAG2.ZYAG_MOTIFA
    	  AND ZYAG_DATDEB = CUR_ZYAG2.ZYAG_DATFIN + 1;
     
          COMMIT;
       END LOOP;
     
       --mise à jour des dates de début contigue lors des abscences consécutives avec un motif différent
       FOR CUR_ZYAG_Q_ALL IN c_zyag_q_all
       LOOP
          IF CUR_ZYAG_Q_ALL.ZYAG_DTABS01 IS NULL OR CUR_ZYAG_Q_ALL.ZYAG_DTABS01 = '' THEN
             UPDATE IHR.HRA_ZYAG_Q A SET A.ZYAG_DTABS01 = CUR_ZYAG_Q_ALL.ZYAG_DATDEB , A.ZYAG_MOTAB1 = CUR_ZYAG_Q_ALL.ZYAG_MOTAB1
             WHERE A.ZY00_SOCCLE = CUR_ZYAG_Q_ALL.ZY00_SOCCLE
             AND A.ZY00_MATCLE = CUR_ZYAG_Q_ALL.ZY00_MATCLE
             AND A.ZYAG_DATDEB = (CUR_ZYAG_Q_ALL.ZYAG_DATFIN + 1);
     
             COMMIT;
          ELSE
    	     UPDATE IHR.HRA_ZYAG_Q A SET A.ZYAG_DTABS01 = CUR_ZYAG_Q_ALL.ZYAG_DTABS01 , A.ZYAG_MOTAB1 = CUR_ZYAG_Q_ALL.ZYAG_MOTAB1
             WHERE A.ZY00_SOCCLE = CUR_ZYAG_Q_ALL.ZY00_SOCCLE
             AND A.ZY00_MATCLE = CUR_ZYAG_Q_ALL.ZY00_MATCLE
             AND A.ZYAG_DATDEB = CUR_ZYAG_Q_ALL.ZYAG_DATFIN + 1;
     
    		 COMMIT;
    	  END IF;
       END LOOP;
     
    END;
    A son exécution ça bloque TOAD et 10-15min plus tard toujours pas la main ... Je kill TOAD et quand je le redémarre je vois bien pas mal de ligne ajoutée à la table cible (entre 500 000 et 600 000)

    Quelqu'un a une idée pour l'optimisation ?

    Merci d'avance

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    4 FULL SCAN autant de curseur et des UPDATE/INSERT unitaires... tu m'étonnes que ça rame

    pourquoi tu fais pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO IHR.HRA_ZYAG_Q
    SELECT * 
    FROM IHR.HRA_ZYAG A
    Plutôt que ton FOR ... LOOP ?

    Ou encore :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          UPDATE IHR.HRA_ZYAG A SET A.ZYAG_PROLON = 'X'
          WHERE (A.ZY00_SOCCLE,A.ZY00_MATCLE,A.ZYAG_MOTIFA,A.ZYAG_DATDEB) IN (SELECT ZY00_SOCCLE,ZY00_MATCLE,ZYAG_MOTIFA,ZYAG_DATFIN + 1 )
          AND (A.ZYAG_PROLON IS NULL OR A.ZYAG_PROLON = '');
    Plutôt que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
       FOR CUR_ZYAG_ALL IN c_zyag_all
       LOOP
          UPDATE IHR.HRA_ZYAG A SET A.ZYAG_PROLON = 'X'
          WHERE A.ZY00_SOCCLE = CUR_ZYAG_ALL.ZY00_SOCCLE
          AND A.ZY00_MATCLE = CUR_ZYAG_ALL.ZY00_MATCLE
          AND A.ZYAG_MOTIFA = CUR_ZYAG_ALL.ZYAG_MOTIFA
          AND A.ZYAG_DATDEB = CUR_ZYAG_ALL.ZYAG_DATFIN + 1
          AND (A.ZYAG_PROLON IS NULL OR A.ZYAG_PROLON = '');
     
          COMMIT;
       END LOOP;
    Et tes ORDER BY génère du tri alors qu'ils sont inutiles

  3. #3
    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
    Chaque fois quand tu fais des insert ou update dans une boucle comme tu le fais dans cette procédure tu plombe les performances
    Donc à la place de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
       --mise à jour des témoins de prolongation oubliés
       FOR CUR_ZYAG_ALL IN c_zyag_all
       LOOP
          UPDATE IHR.HRA_ZYAG A SET A.ZYAG_PROLON = 'X'
          WHERE A.ZY00_SOCCLE = CUR_ZYAG_ALL.ZY00_SOCCLE
          AND A.ZY00_MATCLE = CUR_ZYAG_ALL.ZY00_MATCLE
          AND A.ZYAG_MOTIFA = CUR_ZYAG_ALL.ZYAG_MOTIFA
          AND A.ZYAG_DATDEB = CUR_ZYAG_ALL.ZYAG_DATFIN + 1
          AND (A.ZYAG_PROLON IS NULL OR A.ZYAG_PROLON = '');
     
          COMMIT;
       END LOOP;
    Fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
          UPDATE IHR.HRA_ZYAG A 
             SET A.ZYAG_PROLON = 'X'
          WHERE ZYAG_DATDEB = ZYAG_DATFIN + 1
          AND A.ZYAG_PROLON IS NULL;
    Pareil, au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
       FOR CUR_ZYAG IN c_zyag
       LOOP
          INSERT INTO IHR.HRA_ZYAG_Q
    					(ZY00_SOCCLE,
    					 ZY00_MATCLE,
    ...
    Fait (éventuellement avec le hint APPEND)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    INSERT INTO IHR.HRA_ZYAG_Q
      Select ...
         From IHR.HRA_ZYAG A
    WHERE A.ZYAG_PROLON IS NULL
    Commit en boucle c'est mauvais.
    A.ZYAG_PROLON = '' c'st mauvais.

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    ORDER BY c'est mauvais aussi

  5. #5
    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
    Citation Envoyé par orafrance Voir le message
    ORDER BY c'est mauvais aussi
    Surtout quand il est inutile, comme c'est le cas ici.

  6. #6
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Bon, je vais rajouter une petite couche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CUR_ZYAG c_zyag%ROWTYPE;
    ne sert à rien dans un FOR LOOP
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Points : 342
    Points
    342
    Par défaut
    Surcouche :

    • Un commit a chaque insert/update d'une ligne, c'est lourd. fait un commit toutes les 100 ou 1000 lignes... cela se "regle" en faisant des tests. En fait, je pense que ton programme passe une bonne partie de son temps à faire commit.

    • Quand on est obligé de faire des mouvements en masse de lignes dans PL, on joue du bulk. Cela a pour effet d'optimiser les échanges entre sql et pl, et en plus cela oblige a mettre en oeuvre l'optimisation précédente.

    Mais je n'ai pas l'impression que tu l'es (obligé), si tu peux resoudre un probleme sans passer par pl, avec un maximum de sql, c'est généralement beaucoup mieux. (cf les réponses ci dessus)
    • Il y a des index sur tes tables ? Les statistiques sont à jours ?


    • Si, dans une loop, tu update la ligne courrante d'un curseur, tu a "update... current of..." qui est plus rapide qu'une clause where classique. Au lieu de passer par les index, tu passe par le rowid.

  8. #8
    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
    Citation Envoyé par jmguiche Voir le message
    ...
    • Un commit a chaque insert/update d'une ligne, c'est lourd. fait un commit toutes les 100 ou 1000 lignes... cela se "regle" en faisant des tests. En fait, je pense que ton programme passe une bonne partie de son temps à faire commit.
    Un commit à la fin. Chaque ligne ou toute les 100 ou tout les 1000 c’est le même problème ! Je sais qu’il y a des exceptions mais je vois ce mauvais traitement trop souvent.

    Citation Envoyé par jmguiche Voir le message
    • Quand on est obligé de faire des mouvements en masse de lignes dans PL, on joue du bulk. Cela a pour effet d'optimiser les échanges entre sql et pl, et en plus cela oblige a mettre en oeuvre l'optimisation précédente.

    Mais je n'ai pas l'impression que tu l'es (obligé), si tu peux resoudre un probleme sans passer par pl, avec un maximum de sql, c'est généralement beaucoup mieux. (cf les réponses ci dessus)
    Quand on fait des mouvements de masse en PL/SQL on devait se demander d’abord si il est possible de les faire en SQL

    Citation Envoyé par jmguiche Voir le message
    • Il y a des index sur tes tables ? Les statistiques sont à jours ?


    • Si, dans une loop, tu update la ligne courrante d'un curseur, tu a "update... current of..." qui est plus rapide qu'une clause where classique. Au lieu de passer par les index, tu passe par le rowid.
    Si dans un loop on update la ligne courante il faut se rappeler d’abord que les DML sont des opérations qui s’applique sur des ensembles des données.

  9. #9
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2007
    Messages
    167
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 167
    Points : 112
    Points
    112
    Par défaut
    Bon alors déjà merci à tous de vos réponses !

    Ensuite, j'ai essayé d'appliquer ce que j'ai lu mais j'ai un problème pour transformer :

    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
    CURSOR c_zyag2 IS 
    SELECT * 
    FROM IHR.HRA_ZYAG A
    WHERE A.ZYAG_PROLON = 'X'
    ORDER BY ZY00_SOCCLE ASC, ZY00_MATCLE ASC, ZYAG_NULIGN ASC, ZYAG_DATDEB ASC;
     
    CUR_ZYAG2 c_zyag2%ROWTYPE;
     
     
       --mise à jour des dates de fin d'abscence et du nombre de prolongation selon les témoins de prolongation
       FOR CUR_ZYAG2 IN c_zyag2
       LOOP
          UPDATE IHR.HRA_ZYAG_Q SET ZYAG_DATFIN = CUR_ZYAG2.ZYAG_DATFIN , ZYAG_PROLON = ZYAG_PROLON + 1
    	  WHERE ZY00_SOCCLE = CUR_ZYAG2.ZY00_SOCCLE
    	  AND ZY00_MATCLE = CUR_ZYAG2.ZY00_MATCLE
    	  AND ZYAG_MOTIFA = CUR_ZYAG2.ZYAG_MOTIFA
    	  AND ZYAG_DATDEB = CUR_ZYAG2.ZYAG_DATFIN + 1;
     
          COMMIT;
       END LOOP;
    J'ai essayé de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        UPDATE IHR.HRA_ZYAG_Q A SET A.ZYAG_DATFIN = B.ZYAG_DATFIN , A.ZYAG_PROLON = A.ZYAG_PROLON + 1
    	WHERE (A.ZY00_SOCCLE,A.ZY00_MATCLE,A.ZYAG_MOTIFA,A.ZYAG_DATDEB)
    	IN (SELECT ZY00_SOCCLE,ZY00_MATCLE,ZYAG_MOTIFA,ZYAG_DATFIN + 1
    		FROM IHR.HRA_ZYAG B WHERE B.ZYAG_PROLON = 'X');
     
        COMMIT;
    Mais j'ai une erreur à l'exécution :

    Error on line 0
    UPDATE IHR.HRA_ZYAG_Q A SET A.ZYAG_DATFIN = B.ZYAG_DATFIN , A.ZYAG_PROLON = A.ZY

    ORA-00904: "B"."ZYAG_DATFIN": invalid identifier

    .....

  10. #10
    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
    C'est normal "B"."ZYAG_DATFIN" n'existe pas dans ta requête
    Soit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    UPDATE IHR.HRA_ZYAG_Q A 
       SET A.ZYAG_DATFIN = (Select ZYAG_DATFIN
                              From IHR.HRA_ZYAG
                             Where ...) 
           A.ZYAG_PROLON = A.ZYAG_PROLON + 1
    ...
    Soit Merge

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Points : 342
    Points
    342
    Par défaut
    Citation Envoyé par mnitu Voir le message
    Un commit à la fin. Chaque ligne ou toute les 100 ou tout les 1000 c’est le même problème ! Je sais qu’il y a des exceptions mais je vois ce mauvais traitement trop souvent.



    Quand on fait des mouvements de masse en PL/SQL on devait se demander d’abord si il est possible de les faire en SQL



    Si dans un loop on update la ligne courante il faut se rappeler d’abord que les DML sont des opérations qui s’applique sur des ensembles des données.
    Un commit à la fin, c'est bien si tu as les rollbacks segments qui tiennent et si le fait de verrouiller toutes les lignes pendant tout le traitement ne pose pas de problèmes. La cohabitation d'un batch qui verrouille tout avec de l'interactif n'est pas géniale, d'où des commits réguliers pour limiter le temps de verrouillage des lignes.
    Moi, ce que je vois trop souvent, ce sont des usines à gaz en production à cause de batchs qui obligent inutilement l'interactif à s'arreter et des utilisateurs qui trouvent déplorable d'avoir à attendre "que le batch passe" pour avoir leurs données actualisées.
    Je travaille sur des systemes dont l'objectif est du 24/24, 6/7 voire 7/7, on ne pénalise pas l'interactif à cause des batchs, on n'arrete pas l'interactif à cause des batchs. Je ne connais pas les contraintes de bizoo.
    A part ça, un commit par ligne, c'est attendre un IO par ligne. Un commit toutes les 100 lignes, c'est attendre un IO toutes les 100 lignes. Ce n'est pas le même probleme et c'est sans exception.

    "Quand on fait des mouvements de masse..." Je ne pense pas avoir dit autre chose, sauf contrainte ce dessus. Et Je ne connais pas les contraintes de bizoo.

    "Si dans un loop on update la ligne courante...." En effet, on doit se poser la question de faire un ordre sql globale, sauf si... voire plus haut. Il arrive aussi que le traitement soit trop complexe pour qu'on puisse résoudre le problème seulement avec du sql. Si ce n'était pas le cas, ça se saurait et les langages algorithmiques de type pl ou transac ne seraient pas apparus ou auraient disparus.

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 9
    Points : 17
    Points
    17
    Par défaut
    Désolé mais je ne suis pas du tout d'accord avec toi jmguiche cette pratique est très dangereuse.

    D'une part tu n'as plus du tout de niveau transactionelle.
    Donc en cas d'erreur pas de rollback possible...
    D'autre part rien de tel pour se prendre une erreur ORA-01555 snapshot to old.
    En effet en commitant tu permets à oracle de réutiliser les blocs d'undo.
    De manière générale le fecth accross commit est à proscrire et n'est même pas tolérer dans le standard ANSI à ma connaissance.

    Je pense d'ailleurs que le order by présent dans la requête était la pour limiter ce phénomène....

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Points : 342
    Points
    342
    Par défaut
    Citation Envoyé par ycolin Voir le message
    Désolé mais je ne suis pas du tout d'accord avec toi jmguiche cette pratique est très dangereuse.

    D'une part tu n'as plus du tout de niveau transactionelle.
    Donc en cas d'erreur pas de rollback possible...
    D'autre part rien de tel pour se prendre une erreur ORA-01555 snapshot to old.
    En effet en commitant tu permets à oracle de réutiliser les blocs d'undo.
    De manière générale le fecth accross commit est à proscrire et n'est même pas tolérer dans le standard ANSI à ma connaissance.

    Je pense d'ailleurs que le order by présent dans la requête était la pour limiter ce phénomène....
    Allons, je ne suis pas bête à ce point de ne plus avoir de transaction bien gérée et des batch qui, d'un point de vue fonctionnel, ne doivent qu'être relancés en cas de plantage.

    Le fetch accross commit peut presque toujours s'éviter. Mais il est clair qu'il faut concevoir ses traitement (et les structures technique de la base) en fonction.

    Un snapshot too old est plus simple à gérer que d'expliquer à mes clients que je n'ai pas envie de faire ce qu'ils demandent !
    Il est clair que si je pouvait arreter l'interactif pour passer les batchs, si j'avais des tonnes de rollbacks segment (encore que ça ça va), une bonne requette sql cela irait plus vite et serai plus simple. Mais le monde reel n'est pas toujours conforme à nos souhaits !

  14. #14
    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
    Citation Envoyé par jmguiche Voir le message
    Un commit à la fin, c'est bien si tu as les rollbacks segments qui tiennent et si le fait de verrouiller toutes les lignes pendant tout le traitement ne pose pas de problèmes. La cohabitation d'un batch qui verrouille tout avec de l'interactif n'est pas géniale, d'où des commits réguliers pour limiter le temps de verrouillage des lignes.
    ...
    T’as 100 enregistrement à traiter et tu fait un commit ligne à ligne. T’as 1000 enregistrements à traiter et tu fait un commit tout les 10 ligne, etc. C’est la même chose : 100 commit de trop ! Le besoin d’espace de rollback se calcule ou plutôt s’estime et dans ces cas il y a peu de chances que la taille du lot est un multiple de 10. Les exceptions peuvent être traiter d’un autre manière mais à 99% il n’y pas d’exception mais une ignorence des mécanismes impliqués. Relie le code proposé en début de ce fil de discussion.
    Je ne vois pas en quoi les commit réguliers améliorent la cohabitation batch – transactionnel. Si le batch utilise la méthode de verrouillage pessimiste les commits régulières n’apportent strictement rien. Si le batch utilise la méthode des verrous optimiste il est très probable que le batch dure plus longtemps que nécessaire et qu’on constate des manifestations de type « update restart » ou, peut être dead-lock.

  15. #15
    Membre confirmé Avatar de miloux32
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    545
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 545
    Points : 565
    Points
    565
    Par défaut
    Les seuls cas où c'est interessant ( a mon avis ) :
    - c'est quand tu as peu de rollback-segment par rapport au nombre de lignes à modifier.
    - quand tu as un interet à valider par lot pour une meilleure reprise (les X premiers lots ont été traités pas la peine de les retraiter par la suite )
    C'est pas parce que ca marche que c'est bon!!
    Pensez au bouton "Résolu"
    Je ne réponds pas en privé aux questions

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Points : 342
    Points
    342
    Par défaut
    Citation Envoyé par mnitu Voir le message
    T’as 100 enregistrement à traiter et tu fait un commit ligne à ligne. T’as 1000 enregistrements à traiter et tu fait un commit tout les 10 ligne, etc. C’est la même chose : 100 commit de trop ! Le besoin d’espace de rollback se calcule ou plutôt s’estime et dans ces cas il y a peu de chances que la taille du lot est un multiple de 10. Les exceptions peuvent être traiter d’un autre manière mais à 99% il n’y pas d’exception mais une ignorence des mécanismes impliqués. Relie le code proposé en début de ce fil de discussion.
    Je ne vois pas en quoi les commit réguliers améliorent la cohabitation batch – transactionnel. Si le batch utilise la méthode de verrouillage pessimiste les commits régulières n’apportent strictement rien. Si le batch utilise la méthode des verrous optimiste il est très probable que le batch dure plus longtemps que nécessaire et qu’on constate des manifestations de type « update restart » ou, peut être dead-lock.
    Bon, je repette : quand tu fais 1 commit, tu attend un (mecanisme d') io, quand tu fait mille commit, tu attend mille (mécanisme d')io. Inutile de répeter 100 fois "1000 io de trop", lis et essaye de comprendre ce que les autres écrivent. Personne, et surtout pas moi, ne va dire autre chose que : " si on peut faire en SQL, il faut faire en SQL".

    Tu as sans aucun doute raison. Je n'avait pas intégré le fait que, si une transaction (attente pour un commit) dure 2 heures, le verrou, qu'il soit optimiste ou pessimiste, n'est pas posé à la première modification au plus tard et ne va donc pas être posé pendant 2 heures, avec tout les autres accumulés ! Comment tu dis ? "une ignorence des mécanismes impliqués". (c'est cool comme ton ! )

    Un batch long garde ses verrous, quelque soit l'approche pessimiste ou optimiste, s'il n'y a pas de commit. Ils sont, au plus tard, posé à l'execution de l'update. Si ton premier update s'execute à 15 heures et que ton commit est fait à 17, tu as gardé le verrou 2 heures et les autres verrous en moyenne une heure.
    Ce n'est pas un problème pour tes applications ? C'est inenvisageable pour les miennes. On ne fait pas les même projets.

    Je ne répondais pas forcément dans le cadre précis de la question initiale, comme toi d'ailleurs je pense : ce n'est pas avec 10 lignes de code que l'on batit une solution technique, ce n'est pas avec des à prioris et des idées toutes faites qu'on batit une architecture. On ne peut donner que des pistes sur une question aussi vague que celles que l'on pose ici.
    Par rapport au probleme du premier posteur, je suis incapable d'évaluer la seule solution qui vaille : celle qui résoud le problème, qui est suffisante par rapport à ses contraintes et qui est la moins chere suivant les criteres d'évaluation de son client (client au sens large).

    A part ça, il est vrai que la méthode la moins chere à développer, avec Oracle, c'est presque toujours la meilleure. Encore faut il qu'elle s'adapte aux contraintes (sinon, il faut chercher la moins chere en tenant compte des contraintes) et encore faut il la trouver. Bien souvent, le plus dur, c'est "la faire comprendre".

  17. #17
    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
    Citation Envoyé par jmguiche Voir le message
    ...
    Je n'avait pas intégré le fait que, si une transaction (attente pour un commit) dure 2 heures, le verrou, qu'il soit optimiste ou pessimiste, n'est pas posé à la première modification au plus tard et ne va donc pas être posé pendant 2 heures, avec tout les autres accumulés ! Comment tu dis ? "une ignorence des mécanismes impliqués". (c'est cool comme ton ! )
    ...
    Salut jmguiche,

    Ma remarque concernant « l’ignorance des mécanismes » n’est pas personnelle, ne la considère pas comme t’étant adressée. Comme tu le dis « On ne peut donner que des pistes sur une question aussi vague que celles que l'on pose ici. »
    Cella étant dit j’espère qu’on pourrait continuer à changer nos opinions.

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Points : 342
    Points
    342
    Par défaut
    Sans rancune !

Discussions similaires

  1. Procedure Stockée devient tres lente
    Par messi1987 dans le forum Développement
    Réponses: 3
    Dernier message: 19/06/2015, 14h14
  2. Procédure stockée anormalement lente
    Par james_usus dans le forum MS SQL Server
    Réponses: 26
    Dernier message: 05/03/2012, 09h17
  3. Procédure stockées en java très lente
    Par jproto dans le forum SQL
    Réponses: 3
    Dernier message: 22/05/2008, 13h31
  4. poste de travail lent tres lent
    Par lavazavio dans le forum Windows XP
    Réponses: 3
    Dernier message: 19/06/2007, 09h16
  5. procédure stockée parfois rapide, parfois lente
    Par marcouchi dans le forum MS SQL Server
    Réponses: 11
    Dernier message: 10/01/2007, 09h10

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