Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Bonjour,
je travail sur un programme qui traite un grand nb de données.
En fait, je récupère des infos dans un fichier txt, et de ces infos je fais appel à une procédure stockée qui traite et intègre les info dans une base oracle.
Le code est le suivant :
num1=FileOpen("E:\toto.txt", lineMode!,read!,LockReadWrite!) //Lecture ligne à ligne du fichier a=fileread(num1,chaine_tot) do while a>0 // Pour chaque ligne je récupère les infos qui m'intéresse ls_chaine=Lefttrim(chaine_tot) if integer(left(ls_chaine,1))>0 then longueur = len(ls_chaine) ls_chaine=mid(ls_chaine,3,2)+" "+mid(ls_chaine,5,5)+" "+& right(string((integer(left(ls_chaine,2))+1950)),2)& +" "+mid(ls_chaine,10,5)+mid(ls_chaine,15) ls_hexa=left(ls_chaine,17) j = longueur - 17 chaine_tot = right(ls_chaine,j) ls_chaine=Lefttrim(chaine_tot) longueur = len(ls_chaine) esp = pos(ls_chaine," ",1) ls_vgcro = left(ls_chaine,esp - 1) j = longueur - esp chaine_tot = right(ls_chaine,j) ls_chaine=Lefttrim(chaine_tot) longueur = len(ls_chaine) esp = pos(ls_chaine," ",1) ls_vgcro = left(ls_chaine,esp - 1) j = longueur - esp chaine_tot = right(ls_chaine,j) ls_chaine=Lefttrim(chaine_tot) longueur = len(ls_chaine) lr_vgcro = real(ls_vgcro) esp = pos(ls_chaine," ",1) ls_vgmus = left(ls_chaine,esp - 1) j = longueur - esp chaine_tot = right(ls_chaine,j) lr_vgmus = real(ls_vgmus) ls_vgsol=trim(chaine_tot) lr_vgsol = real(ls_vgsol) //Je fais appel à une procédure stockée DECLARE calcul_ogp PROCEDURE FOR calcul_ogp (:ls_hexa,:as_gen_blup, :as_blup,:ls_vgcro,:ls_vgmus,:ls_vgsol,:lr_vgcro,:lr_vgmus,:lr_vgsol); EXECUTE calcul_ogp; end if a=fileread(num1,chaine_tot) loop fileclose(num1)
La procédure est la suivante :
create procedure calcul_ogp(ls_hexa VARCHAR2,lignee_blup VARCHAR2,blup VARCHAR2, ls_vgcro VARCHAR2, ls_vgmus VARCHAR2, ls_vgsol VARCHAR2,lr_vgcro real,lr_vgmus real,lr_vgsol real) is ll_ani_id number(10); lr_vg real; lr_vg_p real; ls_gen_nom_ani varchar2(30); begin Select animaux.ani_id, genetiques.gen_nom into ll_ani_id, ls_gen_nom_ani from animaux,genetiques where animaux.ani_gen_id = genetiques.gen_id and animaux.ani_num = ls_hexa; If ll_ani_id > 0 THEN Insert into IBP( ibp_ani_id, ibp_lignee, ibp_lignee_blup, ibp_blup ,ibp_vg_crois,ibp_vg_muscle,ibp_vg_m2) Values( ll_ani_id, ls_gen_nom_ani, lignee_blup, blup, ls_vgcro,ls_vgmus,ls_vgsol); IF lignee_blup = 'XXX' THEN lr_vg := (0.22)*lr_vgsol - lr_vgcro + (-1.16)*lr_vgmus; End if; If lignee_blup = 'YYY' THEN lr_vg := (2.8)*lr_vgsol - lr_vgcro + (-2.27)*lr_vgmus; End if; If lignee_blup = 'ZZZ' THEN lr_vg := (2.49)*lr_vgsol - lr_vgcro + (-5.18)*lr_vgmus; End if; End if; IF lignee_blup = 'XXX' THEN lr_vg_p := (0.22)*lr_vgsol - lr_vgcro + (-1.16)*lr_vgmus; End if; If lignee_blup = 'YYY' THEN lr_vg_p := (2.8)*lr_vgsol - lr_vgcro + (-2.27)*lr_vgmus; End if; If lignee_blup = 'ZZZ' THEN lr_vg_p := (2.49)*lr_vgsol - lr_vgcro + (-5.18)*lr_vgmus; End if; Insert into VG_PROD( vg_ani_id, vg_prod, vg_prod_p, VG_gen_nom) Values( ll_ani_id, lr_vg, lr_vg_p, ls_gen_nom_ani); commit; end; /
Le problème est que au fur et à mesure du traitement, je vois la taille du fichier d'échange augmenter jusqu'au crach.
Quelqu'un a t'il une solution à m'apporter?
Merci d'avance.
[edit] balise code
Hors ligne
Juste une question: Pourquoi n'importes-tu pas ton fichier directement dans ORACLE via les fonctions du package UTL_FILE pour le traiter directement dans ta procédure stockée?
Hors ligne
la taille du fichier d'echange ?
comment ca ?
peux tu expliciter un petit peu plus, stplait ? (je suis dur d'oreille...)
Hors ligne
En fait, Ce n'est pas la taille du fichier d'échange qui augmente, c'est l'utilisation de la mémoire. Et quand il n'y en a plus, ça plante.
J'ai essayer le garbagecollect() mais ça ne sert à rien.
Hors ligne
foon a écrit:
Juste une question: Pourquoi n'importes-tu pas ton fichier directement dans ORACLE via les fonctions du package UTL_FILE pour le traiter directement dans ta procédure stockée?
c'est exact, tu peux très facilement traduire ton script de lecture, traitements, écriture en PLSQL, UTL_FILE dispose de toutes les fonctions utiles.
Prérequis : package UTL_FILE installé + accès à des répertoires dans INIT.ORA
Hors ligne
Merci pour votre aide. Je vais suivre votre conseil en utilisant le package UTL_FILE.
Je me permettrais de revenir vers vous si je rencontre des problèmes (Je n'utilise pas beaucoup les procédures stockées).
Hors ligne
Encore mieux, utiliser une external table d'Oracle.
Le principe est de déclarer une table "virtuelle" qui n'a aucune existence physique dans Oracle, mais qui pointe vers un fichier et sait le lire à partir d'une description de format de fichier. On peut ainsi lire différents formats de fichiers, tels que les fichiers CSV ou des fichiers avec des enregistrements et des zones de taille fixe.
Exemple de déclaration de table external qui permet de lire un fichier csv contenant 3 zones :
CREATE TABLE AFRSAS.EXT_ZHR_CO_PERSONNEL ( PERS_LAST_NAME VARCHAR2(20 BYTE) NULL, PERS_FIRST_NAME VARCHAR2(20 BYTE) NULL, PERS_ID VARCHAR2(8 BYTE) NULL ) ORGANIZATION EXTERNAL ( TYPE ORACLE_LOADER DEFAULT DIRECTORY DIR_ZHR_CO1 ACCESS PARAMETERS ( records delimited by '\r\n' nobadfile nologfile nodiscardfile fields terminated by ';' rtrim missing field values are null ( pers_last_name char(20), pers_first_name char(20), pers_id char(8) ) ) LOCATION (DIR_ZHR_CO1:'list_person.csv') ) REJECT LIMIT 0
Hors ligne
Bonjour à tous,
En réfléchissant à mon problème de mémoire, je ne comprends pas pourquoi un code qui ne fais que lire un fichier texte et exécuter une procédure oracle provoque un plantage pour mémoire insuffisante (et cela même si la procédure est lancée 500 000 fois). Je suis actuellement sous PB 6.5 build 444.
Ayant pour projet la migration vers PB 10.5 build 4523, j'ai donc migré cette partie du programme pour tester si j'avais les mêmes problèmes, et là, miracle!, le programme fonctionne très bien et le gestionnaire des tâches me montre que la mémoire n'est utilisée que par le processus oracle et qu'il reste constant.
Mon problème est donc résolu.
Hors ligne
Excellent.
Par contre, je me demandais en regardant de nouveau ton code si le problème
ne pouvait pas être lié au fait qu'il n'y ai pas de CLOSE de
ta procédure calcul_ogp après l'EXECUTE
dans ta boucle:
num1=FileOpen("E:\toto.txt", lineMode!,read!,LockReadWrite!) //Lecture ligne à ligne du fichier a=fileread(num1,chaine_tot) do while a>0 // Pour chaque ligne je récupère les infos qui m'intéresse ls_chaine=Lefttrim(chaine_tot) if integer(left(ls_chaine,1))>0 then longueur = len(ls_chaine) ls_chaine=mid(ls_chaine,3,2)+" "+mid(ls_chaine,5,5)+" "+& right(string((integer(left(ls_chaine,2))+1950)),2)& +" "+mid(ls_chaine,10,5)+mid(ls_chaine,15) ls_hexa=left(ls_chaine,17) j = longueur - 17 chaine_tot = right(ls_chaine,j) ls_chaine=Lefttrim(chaine_tot) longueur = len(ls_chaine) esp = pos(ls_chaine," ",1) ls_vgcro = left(ls_chaine,esp - 1) j = longueur - esp chaine_tot = right(ls_chaine,j) ls_chaine=Lefttrim(chaine_tot) longueur = len(ls_chaine) esp = pos(ls_chaine," ",1) ls_vgcro = left(ls_chaine,esp - 1) j = longueur - esp chaine_tot = right(ls_chaine,j) ls_chaine=Lefttrim(chaine_tot) longueur = len(ls_chaine) lr_vgcro = real(ls_vgcro) esp = pos(ls_chaine," ",1) ls_vgmus = left(ls_chaine,esp - 1) j = longueur - esp chaine_tot = right(ls_chaine,j) lr_vgmus = real(ls_vgmus) ls_vgsol=trim(chaine_tot) lr_vgsol = real(ls_vgsol) //Je fais appel à une procédure stockée DECLARE calcul_ogp PROCEDURE FOR calcul_ogp (:ls_hexa,:as_gen_blup, :as_blup,:ls_vgcro,:ls_vgmus,:ls_vgsol,:lr_vgcro,:lr_vgmus,:lr_vgsol); EXECUTE calcul_ogp; CLOSE calcul_ogp; end if a=fileread(num1,chaine_tot) loop fileclose(num1)
Hors ligne
Salut Foon,
Je vais vérifier si j'ai les mêmes problèmes en ajoutant un CLOSE après l'exécution de ma procédure.
Hors ligne
Salut Foon,
Après un nouveau test, et en ajoutant un CLOSE à ma procédure, j'ai quand même le problème de mémoire.
Je pense que ça doit venir de la version de PB! Mais sans grande certitude.
Merci pour ton aide.
Hors ligne