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 :

[OracleText]Comment diminuer la durée d'une conversion de BFILE en HTML


Sujet :

PL/SQL Oracle

  1. #1
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut [OracleText]Comment diminuer la durée d'une conversion de BFILE en HTML
    EDIT : message réintroduit suite à la panne de serveur
    Bonjour,

    J'ai une table contenant une colonne BFILE pointant vers des documents Word, Excel, PDF, etc sur un système de fichier. et je converti cette colonne en un contenu HTML pour une indexation future avec Oracle Text.

    Ce que j'ai, une table contenant 3 millions d'enregistrements, le script de création volontairement réduit aux colonnes utiles pour cette discussion :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TABLE DGTVISTA.VIS_DOCUMENTS_T (    DOC_ID           NUMBER(10)                   NOT NULL,    DOC_CLOB         CLOB,   DOC_BFILE        BFILE )
    Une procédure qui boucle sur une plage de données de la table, convertissant pour chaque ligne la colonne DOC_BFILE en HTML dans la colonne DOC_CLOB via un convertisseur fourni par Oracle Text :

    Code sql : 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
     
    CREATE OR REPLACE PROCEDURE DGTVISTA.fast_way_byrange_OLD (
       beginrownum   NUMBER,
       endrownum     NUMBER
    )
    IS
       ltimestamp_start   TIMESTAMP;
       ltimestamp_stop    TIMESTAMP;
       linterval_diff     INTERVAL DAY TO SECOND;
       n                  NUMBER                 := 0;
       c                  CLOB;
     
       TYPE ARRAY IS TABLE OF vis_documents_t%ROWTYPE;
     
       l_data             ARRAY;
     
       TYPE parent_rec IS RECORD (
          part_num    DBMS_SQL.number_table,
          part_name   DBMS_SQL.bfile_table
       );
     
       p_rec              parent_rec;
     
       CURSOR cur
       IS
          SELECT *
            FROM vis_documents_t
           WHERE doc_id IN (SELECT doc_id
                              FROM (SELECT a.*, ROWNUM rnum
                                      FROM (SELECT doc_id
                                              FROM vis_documents_t) a
                                     WHERE ROWNUM <= endrownum)
                             WHERE rnum >= beginrownum);
    BEGIN
       ltimestamp_start := SYSTIMESTAMP;
       DBMS_OUTPUT.put_line (ltimestamp_start);
     
       OPEN cur;
     
       LOOP
          FETCH cur
          BULK COLLECT INTO l_data LIMIT 2000;
     
          FOR i IN 1 .. l_data.COUNT
          LOOP
             BEGIN
                ctx_doc.policy_filter ('dgt_policy', l_data (i).doc_bfile, c);
     
                UPDATE vis_documents_t
                   SET doc_clob = c
                 WHERE doc_id = l_data (i).doc_id;
             EXCEPTION
                WHEN OTHERS
                THEN
                   NULL;
             END;
          END LOOP;
     
          EXIT WHEN cur%NOTFOUND;
       END LOOP;
     
       CLOSE cur;
     
       COMMIT;
       ltimestamp_stop := SYSTIMESTAMP;
       DBMS_OUTPUT.put_line (ltimestamp_stop);
       linterval_diff := ltimestamp_stop - ltimestamp_start;
       DBMS_OUTPUT.put_line (   CHR (10)
                             || LPAD ('=', 22, '=')
                             || CHR (10)
                             || '  Runtime Difference'
                             || CHR (10)
                             || LPAD ('=', 22, '=')
                            );
       DBMS_OUTPUT.put_line (   '     Days : '
                             || EXTRACT (DAY FROM linterval_diff)
                             || CHR (10)
                             || '    Hours : '
                             || EXTRACT (HOUR FROM linterval_diff)
                             || CHR (10)
                             || '  Minutes : '
                             || EXTRACT (MINUTE FROM linterval_diff)
                             || CHR (10)
                             || '  Seconds : '
                             || EXTRACT (SECOND FROM linterval_diff)
                            );
    END fast_way_byrange_OLD;
    /

    Pour exécuter cette procédure, j'ai un script sous Unix qui lance en tâche de fond 5 fois un autre script (voir script suivant) responsable d'exécuter la procédure vue précédemment :

    ( NB : $DU $DP $DD sont les identifiants de connexions à la base de données Oracle, et les 2 derniers paramètres les bornes pour la procédure stockée vue précédemment )

    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
        (
    ./single_part_tab.sh $DU $DP $DD 0 50000
    ) &
     
    (
    ./single_part_tab.sh $DU $DP $DD 50001 100000
    ) &
     
    (
    ./single_part_tab.sh $DU $DP $DD 100001 150000
    ) &
     
    (
    ./single_part_tab.sh $DU $DP $DD 150001 200000
    ) &
     
    (
    ./single_part_tab.sh $DU $DP $DD 200001 250000
    ) &
     
    wait
    Le script single_part_tab.sh responsable d'appeler la procédure stockée vue au dessus :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        sqlplus -S $1/$2@$3 << EOF > logs/log_part_tab_$4_to_$5.log
    SET SERVEROUTPUT ON
    TIMING START mytimer_single_part_tab
    exec fast_way_byrange ($4,$5);
    TIMING STOP mytimer_part_tab
    exit
    EOF
    J'ai lancé le tout hier (avec les plages de données de ce post) et le traitement a duré plus de 9 heures, pour seulement 250 000 enregistrements convertis en HTML, sachant que j'en ai 3 millions au final ça risque de prendre du temps, trop de temps.

    Aussi, auriez vous des idées ? des conseils ? des corrections à apporter ? pour que ce traitement soit optimisé.

    Et si vous voyez quelque chose de mauvais dans mon code merci d'avance pour vos précisions.

    Merci d'avance

  2. #2
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    EDIT : Réponse initiale de la part de Mcm

    Si, tout plein :
    1 : C'est pas bien les select * pour des curseurs ! Tu ramènes tout alors que tout n'est pas nécessaire... surtout le CLOB (sauf erreur de ma part)!

    2 : faudrait un ordre de tri pour les rownum.

    Code sql : 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
     
    CREATE OR REPLACE PROCEDURE fast_way_byrange (
       beginrownum   NUMBER,
       endrownum     NUMBER
    )
    IS
       ltimestamp_start   TIMESTAMP;
       ltimestamp_stop    TIMESTAMP;
       linterval_diff     INTERVAL DAY TO SECOND;
       c                  CLOB;
     
    TYPE    REC_DOC IS RECORD( DOC_ID  NUMBER(10), DOC_BFILE BFILE);
    TYPE    TAB_DOC IS TABLE OF REC_DOC INDEX BY BINARY_INTEGER;
      l_data  TAB_DOC;
     
    BEGIN
     
       ltimestamp_start := SYSTIMESTAMP;
       DBMS_OUTPUT.PUT_LINE (ltimestamp_start);
     
        SELECT doc_id, doc_bfile
        BULK COLLECT INTO l_data 
        FROM (SELECT a.doc_id, a.doc_bfile, ROWNUM rnum
            FROM (    SELECT doc_id, doc_bfile
                FROM VIS_DOCUMENTS_T
                ORDER BY 1) a
            WHERE ROWNUM <= endrownum)
        WHERE rnum >= beginrownum);
     
     
       FOR i IN 1 .. l_data.COUNT
       LOOP
          BEGIN
             ctx_doc.policy_filter ('dgt_policy', l_data(i).doc_bfile, c);
     
             UPDATE VIS_DOCUMENTS_T
                SET doc_clob = c
              WHERE doc_id = l_data(i).doc_id;
          EXCEPTION
             WHEN OTHERS
             THEN      NULL;
          END;
       END LOOP;
     
       COMMIT;
     
       ltimestamp_stop := SYSTIMESTAMP;
       DBMS_OUTPUT.PUT_LINE (ltimestamp_stop);
       linterval_diff := ltimestamp_stop - ltimestamp_start;
       DBMS_OUTPUT.PUT_LINE (   CHR (10)
                             || LPAD ('=', 22, '=')
                             || CHR (10)
                             || '  Runtime Difference'
                             || CHR (10)
                             || LPAD ('=', 22, '=')
                            );
       DBMS_OUTPUT.PUT_LINE (   '     Days : '
                             || EXTRACT (DAY FROM linterval_diff)
                             || CHR (10)
                             || '    Hours : '
                             || EXTRACT (HOUR FROM linterval_diff)
                             || CHR (10)
                             || '  Minutes : '
                             || EXTRACT (MINUTE FROM linterval_diff)
                             || CHR (10)
                             || '  Seconds : '
                             || EXTRACT (SECOND FROM linterval_diff)
                            );
    END fast_way_byrange;
    /

  3. #3
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    Je vais modifier mon code et faire le test, mais je ne pense pas que le gain de temps sera significatif...

    Aurais tu d'autres idées sur ce traitement long ? parallélisation des traitements, optimisation de la table... ?

    Merci d'avance

  4. #4
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    Voilà maintenant le code modifié de ma procédure :

    Code sql : 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
     
    CREATE OR REPLACE PROCEDURE DGTVISTA.fast_way_byrange (
       beginrownum   NUMBER,
       endrownum     NUMBER
    )
    IS
       ltimestamp_start   TIMESTAMP;
       ltimestamp_stop    TIMESTAMP;
       linterval_diff     INTERVAL DAY TO SECOND;
       n                  NUMBER                 := 0;
       c                  CLOB;
     
       TYPE rec_doc IS RECORD (
          doc_id      NUMBER (10),
          doc_bfile   BFILE
       );
     
       TYPE tab_doc IS TABLE OF rec_doc
          INDEX BY BINARY_INTEGER;
     
       l_data             tab_doc;
    BEGIN
       ltimestamp_start := SYSTIMESTAMP;
       DBMS_OUTPUT.put_line (ltimestamp_start);
     
       SELECT doc_id,
              doc_bfile
       BULK COLLECT INTO l_data
         FROM (SELECT a.doc_id, a.doc_bfile, ROWNUM rnum
                 FROM (SELECT   doc_id, doc_bfile
                           FROM vis_documents_t
                       ORDER BY 1) a
                WHERE ROWNUM <= endrownum)
        WHERE rnum >= beginrownum;
     
       FOR i IN 1 .. l_data.COUNT
       LOOP
          BEGIN
             ctx_doc.policy_filter ('dgt_policy', l_data (i).doc_bfile, c);
     
             UPDATE vis_documents_t
                SET doc_clob = c
              WHERE doc_id = l_data (i).doc_id;
          EXCEPTION
             WHEN OTHERS
             THEN
                NULL;
          END;
       END LOOP;
     
       COMMIT;
       ltimestamp_stop := SYSTIMESTAMP;
       DBMS_OUTPUT.put_line (ltimestamp_stop);
       linterval_diff := ltimestamp_stop - ltimestamp_start;
       DBMS_OUTPUT.put_line (   CHR (10)
                             || LPAD ('=', 22, '=')
                             || CHR (10)
                             || '  Runtime Difference'
                             || CHR (10)
                             || LPAD ('=', 22, '=')
                            );
       DBMS_OUTPUT.put_line (   '     Days : '
                             || EXTRACT (DAY FROM linterval_diff)
                             || CHR (10)
                             || '    Hours : '
                             || EXTRACT (HOUR FROM linterval_diff)
                             || CHR (10)
                             || '  Minutes : '
                             || EXTRACT (MINUTE FROM linterval_diff)
                             || CHR (10)
                             || '  Seconds : '
                             || EXTRACT (SECOND FROM linterval_diff)
                            );
    END fast_way_byrange;
    /

    Et le résultat des courses, le temps d'execution du traitement le plus long de 2000001 à 250000:

    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
    29-JUL-08 09.05.51.677131 AM
    29-JUL-08 02.04.32.567258 PM
     
    ======================
      Runtime Difference
    ======================
    Days : 0
        Hours : 4
      Minutes : 58
      Seconds : 40.890127
     
    PL/SQL procedure successfully completed.
     
    timing for: mytimer_single_part_tab
    Elapsed: 04:58:41.01
    Le plus court des 5 traitements, de 0 à 50000 a pris :
    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
     
    29-JUL-08 09.05.51.671832 AM
    29-JUL-08 12.12.43.254256 PM
     
    ======================
      Runtime Difference
    ======================
    Days : 0
        Hours : 3
      Minutes : 6
      Seconds : 51.582424
     
    PL/SQL procedure successfully completed.
     
    timing for: mytimer_single_part_tab
    Elapsed: 03:06:51.74
    Je viens de lancer les traitements par tranches de 250 000 enregistrements, lancé hier à 18 heures j'attends encore le résultat à l'heure où j'écris.

    D'autres idées d'optimisation, ou alors c'est le temps normal que doit prendre cette conversion de BFILE en HTML ?

    Merci d'avance pour les nouvelles idées.

  5. #5
    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
    Bourrin !!
    Essaye de lancer sur 1 petit nombre d'enreg (5000 ou 1000) par exemple.

    Essaye de voir ce qui dure le plus longtemps avec DBMS_UTILITY.GET_TIME;

    C'est surement cette partie : ctx_doc.policy_filter

    En fait en reprenant le code, tu n'as pas besoin d'utiliser des collections.

    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
    CREATE OR REPLACE PROCEDURE DGTVISTA.fast_way_byrange (
       beginrownum   NUMBER,
       endrownum     NUMBER
    )
    IS
       ltimestamp_start   TIMESTAMP;
       ltimestamp_stop    TIMESTAMP;
       linterval_diff     INTERVAL DAY TO SECOND;
       n                  NUMBER                 := 0;
       c                  CLOB;
     
       -- Pour test de durée.
       v1				NUMBER;
       v2				NUMBER;
       duree1 			NUMBER := 0;
       duree2 			NUMBER := 0;
    BEGIN
     
       ltimestamp_start := SYSTIMESTAMP;
       DBMS_OUTPUT.PUT_LINE (ltimestamp_start);
     
       FOR i IN (SELECT doc_id, doc_bfile
    		   FROM (SELECT a.doc_id, a.doc_bfile, ROWNUM rnum
    			        FROM (SELECT   doc_id, doc_bfile
    				          FROM vis_documents_t
    				           ORDER BY 1) a
    				 WHERE ROWNUM <= endrownum)
    		   WHERE rnum >= beginrownum;)
       LOOP
          BEGIN
    		v1 := DBMS_UTILITY.GET_TIME;
    		ctx_doc.policy_filter ('dgt_policy', i.doc_bfile, c);
    		v2 := DBMS_UTILITY.GET_TIME;
    		duree1 := duree1 + (v2-v1);
     
    		v1 := DBMS_UTILITY.GET_TIME;
    		UPDATE VIS_DOCUMENTS_T
    		SET doc_clob = c
    		WHERE doc_id = i.doc_id;
    		v2 := DBMS_UTILITY.GET_TIME;
    		duree2 := duree2 + (v2-v1);
          EXCEPTION
             WHEN OTHERS
             THEN
                NULL;
          END;
       END LOOP;
     
       COMMIT;
     
       DBMS_OUTPUT.PUT_LINE('ctx_doc.policy_filter : '|| duree1);
       DBMS_OUTPUT.PUT_LINE('Update : '|| duree2);
     
       ltimestamp_stop := SYSTIMESTAMP;
       DBMS_OUTPUT.PUT_LINE (ltimestamp_stop);
       linterval_diff := ltimestamp_stop - ltimestamp_start;
       DBMS_OUTPUT.PUT_LINE (   CHR (10)|| LPAD ('=', 22, '=')|| CHR (10)
                             || '  Runtime Difference' || CHR (10)
                             || LPAD ('=', 22, '=') );
       DBMS_OUTPUT.PUT_LINE (   '     Days : '|| EXTRACT (DAY FROM linterval_diff)|| CHR (10)
                             || '    Hours : '|| EXTRACT (HOUR FROM linterval_diff)|| CHR (10)
                             || '  Minutes : '|| EXTRACT (MINUTE FROM linterval_diff)|| CHR (10)
                             || '  Seconds : '|| EXTRACT (SECOND FROM linterval_diff)                        );
    END fast_way_byrange;
    /
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  6. #6
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    Ouf...mon traitement par tranches de 250 000 pour une table de 1 Millions de lignes vient de finir...après plus d'une journée, c'est bizarre car j'ai l'impression que les traitements ne sont pas lancés en parallèle, le plus long :

    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
    29-JUL-08 03.59.41.132924 PM
    30-JUL-08 04.34.51.152583 PM
     
    ======================
      Runtime Difference
    ======================
    Days : 1
        Hours : 0
      Minutes : 35
      Seconds : 10.019659
     
    PL/SQL procedure successfully completed.
     
    timing for: mytimer_single_part_tab
    Elapsed: 24:35:10.96
    Et le plus rapide des 5 traitements par plage de 250 000 a duré un peu plus de 11 heures :
    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
     
    29-JUL-08 03.59.41.099733 PM
    30-JUL-08 03.04.36.344466 AM
     
    ======================
      Runtime Difference
    ======================
    Days : 0
        Hours : 11
      Minutes : 4
      Seconds : 55.244733
     
    PL/SQL procedure successfully completed.
     
    timing for: mytimer_single_part_tab
    Elapsed: 11:04:57.18
    Bourrin tu disais ?

    Sinon, je viens de reprendre ton dernier code pour la procédure et j'ai lancé mon script pour une plage de 0 à 1000, le résultat des courses :

    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
    30-JUL-08 05.09.00.080053 PM
    ctx_doc.policy_filter : 20023
    Update : 7231
    30-JUL-08 05.13.35.363752 PM
     
    ======================
      Runtime Difference
    ======================
    Days : 0
        Hours : 0
      Minutes : 4
      Seconds : 35.283699
     
    PL/SQL procedure successfully completed.
     
    timing for: mytimer_single_part_tab
    Elapsed: 00:04:35.43
    sauf erreur de ma part, la fonction DBMS_UTILITY.GET_TIME ramène des centièmes de secondes, donc on aurait environ 200 secondes pour le ctx_doc.policy_filter et 72 secondes pour Update.

    Y aurait il des possibilités d'optimisations ? index sur la table pour accèlérer l'update ? d'autres choses ?

    D'autres pistes ?

    Merci d'avance

  7. #7
    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
    index sur la table pour accèlérer l'update ?
    Heu, t'as pas d'index sur VIS_DOCUMENTS_T.doc_id ?
    Je pense que si vu que c'est une table de 3M enreg.

    Mais bon, le résultat est là :
    ctx_doc.policy_filter 200 s pour 1000 lignes.
    Tu as 1M de lignes donc 1000 fois ce traitement
    => 200 000 s = 55h de temps total à priori non compressible (mais je ne connais pas du tout ce package oracle).
    J'ai pas tout saisi dans ton batch, mais tu parallélises, c'est ça ?

    Pour l'update, c'est la DML la plus coûteuse sur Oracle.
    Peut-être que faire un insert de l'id et du clob dans table tempo, puis de passer un update de masse à la fin de la boucle fera mieux, mais les CLOB ayant une façon spéciale d'être gérés, c'est juste une idée comme ça.

    Je viens de penser à un truc : Ce qui est chiant c'est de faire une boucle, [de lancer une procédure et de faire un update] donc 3M de fois
    Si tu fais une fonction qui prend en param le BFILE et te renvoies le CLOB, tu fais l'update directement.

    Genre :
    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
     
    SELECT min(doc_id), max(doc_id)
    into v_min, v_max
    FROM (SELECT a.doc_id, ROWNUM rnum
            FROM (SELECT   doc_id FROM vis_documents_t   ORDER BY 1) a
    	 WHERE ROWNUM <= endrownum)
    WHERE rnum >= beginrownum;
     
    UPDATE VIS_DOCUMENTS_T
    SET doc_clob = f_policy_filter(doc_bfile)
    WHERE doc_id BETWEEN v_min AND v_max;
     
     
    Avec 
    f_policy_filter(p_doc IN BFILE)
    return CLOB as
     c CLOB;
    begin
    ctx_doc.policy_filter ('dgt_policy', p_doc, c);
    return c;
    end;
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  8. #8
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    Sur ma table, j'ai quand même un index sur DOC_ID :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CREATE UNIQUE INDEX DGTVISTA.PK_DOC_ID ON DGTVISTA.VIS_DOCUMENTS_T
    (DOC_ID);

    Mais est ce suffisant, existe t'il des paramètres de création de l'index qui pourraient l'améliorer ?

    Concernant mes scripts lancé sous UNIX, l'extrait suivant exécutera le script single_part_tab.sh (script qui ouvre une connexion à la base, et appelle la procédure) par deux fois, en tâche de fond :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    (
    ./single_part_tab.sh $DU $DP $DD 0 1000
    ) &
     
    (
    ./single_part_tab.sh $DU $DP $DD 1001 2000
    ) &
    Je ne sais pas si on peut appeler ça du parallélisme car certains scripts aboutissent, mais bien avant les autres pour le même nombre d'enregistrements à traiter. Existe t'il une solution entièrement sous oracle pour exécuter en parallèle ma procédure ?

    Je viens de faire les modifications avec la fonction que tu proposes à inclure dans l'update, voilà les résultats du log :

    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
    31-JUL-08 02.36.55.876970 PM
    31-JUL-08 02.41.16.582661 PM
     
    ======================
      Runtime Difference
    ======================
    Days : 0
        Hours : 0
      Minutes : 4
      Seconds : 20.705691
     
    PL/SQL procedure successfully completed.
     
    timing for: mytimer_single_part_tab
    Elapsed: 00:04:20.77
    J'ai lancé la procédure plusieurs fois, je trouve que les temps sont similaires à la version précédentes (peut être quelques secondes en moins...) mais en attendant le code est plus clair.

    Je vais tenter le coup de la table temporaire et de l'insert et update de masse par la suite pour voir.

    Si il y a d'autres idées ? notamment dans la parralèlisation du traitement ?

    Merci d'avance

  9. #9
    Expert éminent
    Avatar de elitost
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2003
    Messages
    1 985
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2003
    Messages : 1 985
    Points : 6 566
    Points
    6 566
    Par défaut
    L'utilisation d'une table temporaire avec INSERT puis l'update ne fait pas gagner significativement du temps...

    J'ai tenté de mettre des HINTs pour paralléliser l'update mais je n'ai pas l'impression que ça fonctionne, en tout cas au niveau de la durée du traitement, pas de changement, mais peut être que j'utilise mal la fonctionnalité, que la base n'est pas paramétrée pour.

    D'autres idées , ou alors nous en restons là ?

Discussions similaires

  1. Comment obtenir la durée d'une vidéo?
    Par bakabdel dans le forum ASP.NET
    Réponses: 0
    Dernier message: 13/04/2009, 13h39
  2. find / grep : comment diminuer la longueur d'une ligne en sortie
    Par gifffftane dans le forum Shell et commandes GNU
    Réponses: 4
    Dernier message: 11/04/2007, 15h10
  3. Réponses: 3
    Dernier message: 19/12/2006, 17h43
  4. Comment limiter la durée d'utilisation d'une appli
    Par le lynx dans le forum Access
    Réponses: 2
    Dernier message: 26/06/2006, 16h23
  5. Réponses: 3
    Dernier message: 27/04/2006, 11h37

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