Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 10/09/2008, 13h35   #1
Candidat au titre de Membre du Club
 
Inscription : mars 2005
Messages : 56
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 56
Points : 11
Points : 11
Par défaut Aide pour optimisation d'un import xml

Salut tout le monde,

je suis en train de faire un import xml vers ma base de données (les balises du fichier xml ne correspondent pas au nom des champs des tables de ma BDD)

mon import marche correctement, mais il est super long.
je suppose que c'est du a la taille de mon fichier (600 000 lignes a peu pret)
pour cette taille il met environ 5h
me demandez pas de reduire le fichier, je sais que c'est enorme juste pour du texte, mais ce n'est malheureusement pas possible, le client n'y connais rien, et veut que ce soit rapide, enfin, pas trop long et a besoin de toutes les données dedans

j'ai essayé pas mal de truc pour reduire le temps, mais quasiment rien a marché.
par exemple, supprimer au maximum les variable temporaire.
Code :
1
2
3
4
5
v1:=lire_balise('Code_Valeur',element);	
v2:=lire_balise('Titre_Valeur',element);
v_com:=lire_balise('Commentaire',element);
var_ID_Valeur := var_ID_Valeur + 1;
INSERT INTO ARCHIV_Valeur VALUES (var_ID_Valeur,var_ID_DFIDUI,v1,v2,var_rang_valeur,v_com,NULL,'');
donc supprimer v1,v2,v_com pour mettre directement les appels de la fontion a la place
Code :
INSERT INTO ARCHIV_Valeur VALUES (var_ID_Valeur,var_ID_DFIDUI,lire_balise('Code_Valeur',element),lire_balise('Titre_Valeur',element),var_rang_valeur,lire_balise('Commentaire',element),NULL,'');
vu que ca va passer tres souvent par la, je peux peut etre gagner du temps la dessus. (affectation etc.. ca peut prendre un pti bout de temps si on le repete beaucoup, non ? )

mais lorsque je compile ca sous forms, il me met:
Code :
1
2
Erreur 425, ligne 130, colonne 85
dans l'instruction SQL, l'argument de fonction doit etre de type sql
le probleme vient de la variable 'element' (quand je clique sur cette erreur, le cureseur se place juste avant le mot element) qui est de type xmldom.DOMElement et qui va tres bien avec ma fonction lire_balise (qui prend le nom de la balise et le DOMElement)


sinon, existe t-il un moyen pour n'executer les requetes sql que a un certain moment ?
par exemple, les stocker en memoire puis les faire s'executer, pour peut etre reduire les allez venu entre la bdd et le code (j'en sais rien, c'est juste une hypothese)

j'avais pensé aussi a utiliser une sorte de for each pour parcourir la liste de node a la place du for. car si c'est stocké dans une liste chainée et que les elements 0,1,2,3.. ne sont pas trié correctement, il faut les rechercher, donc perte de temps
Code :
1
2
3
Liste_Implementation := xmldom.getElementsByTagName(element_ebit, 'PID');
	len_Implementation := xmldom.getLength(Liste_Implementation);
	FOR numero_PID IN 0..len_Implementation-1 loop
mais je n'ai pas reussi a trouver un code le faisant

derniere solution, mais assez galere, c'est d'essayer de le passer en SAX grace a java, mais je ne sais pas si on gagnerai beaucoup de temps, et ca n'a pas l'air tres facile.


Si vous avez des idées, ou des corrections dans mon code, ou autre, ca serait hyper cool, moi j'suis a court d'idées

je mets mon code en entier en fichier joint, enfin, la fonction qui me permet de parcourir le document et inserer dans ma bdd (Importer_Tables_Xml), et la fontion lire_balise qui retourne ce que contient une balise (en passant un domElement et un nom de balise)

merci

mike
Fichiers attachés
Type de fichier : txt importe_xml.txt (11,0 Ko, 10 affichages)
mikeOSX est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/09/2008, 14h39   #2
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 320
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 320
Points : 5 839
Points : 5 839
Jetez un œil sur ce lien. Peut être ça aide.
Et peut être ici aussi.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/09/2008, 10h30   #3
Candidat au titre de Membre du Club
 
Inscription : mars 2005
Messages : 56
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 56
Points : 11
Points : 11
merci pour ta reponse, je vais essayer de voir ca
si vous avez d'autres idées, n'hesitez pas
mikeOSX est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/09/2008, 11h28   #4
Candidat au titre de Membre du Club
 
Inscription : mars 2005
Messages : 56
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 56
Points : 11
Points : 11
j'ai lu les documents, mais ca ne m'a pas fait vraiment avancé.

le truc que j'aimerai bien tester, c'est supprimer mes variables intermediaires (v1,v2...).

Code :
1
2
3
4
5
v1:=lire_balise('Code_Valeur',element);	
v2:=lire_balise('Titre_Valeur',element);
v_com:=lire_balise('Commentaire',element);
var_ID_Valeur := var_ID_Valeur + 1;
INSERT INTO ARCHIV_Valeur VALUES (var_ID_Valeur,var_ID_DFIDUI,v1,v2,var_rang_valeur,v_com,NULL,'');
donc supprimer v1,v2,v_com pour mettre directement les appels de la fontion dans la requete
Code :
INSERT INTO ARCHIV_Valeur VALUES (var_ID_Valeur,var_ID_DFIDUI,lire_balise('Code_Valeur',element),lire_balise('Titre_Valeur',element),var_rang_valeur,lire_balise('Commentaire',element),NULL,'');
vu que ca va passer tres souvent par la, je peux peut etre gagner du temps la dessus. (affectation etc.. ca peut prendre un pti bout de temps si on le repete beaucoup, non ? )

mais lorsque je compile ca sous forms, il me met:
Code :
1
2
Erreur 425, ligne 130, colonne 85
dans l'instruction SQL, l'argument de fonction doit etre de type sql
le probleme vient de la variable 'element' (quand je clique sur cette erreur, le cureseur se place juste avant le mot element) qui est de type xmldom.DOMElement et qui va tres bien avec ma fonction lire_balise (qui prend le nom de la balise et le DOMElement)

si vous aviez un truc pour que ca marche, ca serait sympa

mike
mikeOSX est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/09/2008, 14h57   #5
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 320
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 320
Points : 5 839
Points : 5 839
Ce n’est pas en supprimant tes variables de travail que tu gagneras du temps mais dans la logique du traitement.
Exemple au lieu d’écrire une procédure qui fait
Code :
1
2
3
4
5
 
Loop
  ...
  INSERT INTO TABLE
End loop
Tu pourrais employer les procédures pipelined pour écrire quelque chose de type
Code :
1
2
 
INSERT INTO TABLE SELECT FROM pipelined_procédure
Mais avant d’arriver à ça je pense que tes problèmes sont dans l’algorithme d’exploitation de ton fichier xml ; je vais essayer de l’étudier.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/09/2008, 12h42   #6
Candidat au titre de Membre du Club
 
Inscription : mars 2005
Messages : 56
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 56
Points : 11
Points : 11
merci mnitu

je sais que je ne gagnerai pas enormement en supprimant des variables, mais bon, c'etait une idée comme ca, car je n'en avais pas d'autres

j'ai pas tout compris aux procedures piplined, mais tu penses que ca serait plus rapide ?

si t'as d'autres idées, je suis preneur

merci

mike
mikeOSX est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/09/2008, 10h27   #7
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 320
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 320
Points : 5 839
Points : 5 839
Commençons doucement !
La première chose à faire este d’essayer de comprendre ou le temps passe (valable pour tout problème d’optimisation)! Pour cella il faut instrumentaliser un peu le code pour avoir cette information ou à la limite exécuter la procédure avec une trace sql.
Ensuite, dans la ligne du plus petit effort, essayez pour l’instant d’utiliser les collections pour les boucles imbriquées. CAD : utilisez des collections pour accumuler les enregistrements avant de faire des bulks insert avec FOR ALL.
.../...
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/09/2008, 13h14   #8
Candidat au titre de Membre du Club
 
Inscription : mars 2005
Messages : 56
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 56
Points : 11
Points : 11
j'ai fait un trace, et analysé:

en gros, sur les 5h,
il y a 1 minutes et quelques pour tous les insert
27 minutes sur les select

et le reste en recuperant les temps avec sysdate (un sysdate avant des lire_balise, et un apres, puis on ajoute la difference a une autre variable)
j'atteinds un peu plus de 4h

donc c'est la recuperation des valeurs du XML qui prennent un maximum de temps

les collections, c'est une sorte de tableau ou on stocke les données ?
a moins que j'ai rien compris a la doc que je viens de lire

mike
mikeOSX est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/09/2008, 14h39   #9
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 320
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 320
Points : 5 839
Points : 5 839
Bref le problème est dans la récupération des valeurs stockée dans le fichier XML. Le problème est que d’après ce que j’ai compris le parser PL/SQL est un DOM parser et cella signifie que il aura récréation en mémoire du fichier XML. Dans ton cas – pas de modification des informations contenues dans la structure XML cella coûte assez cher. Il semble qu’il est plus approprié d’utiliser un SAX parser dans ces conditions. Mais pour cela il faut changer de langage, utiliser java ou C.
Concernant les collections laisse tomber, tu gagneras seulement sur les quelques minutes d’insertion.

PS. Pour mesurer le temps tu disposes d’une fonction dbms_utility.get_time.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/09/2008, 15h57   #10
Candidat au titre de Membre du Club
 
Inscription : mars 2005
Messages : 56
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 56
Points : 11
Points : 11
hum...
bon ok, on va essayer de passer par java et sax

et oui, le parser est un dom parser, il me semble que c'est le seul qui existe en pl/sql (on se demande pourquoi... )

merci beaucoup en tout cas
je reviendrai par ici si j'ai des problemes avec le java
mikeOSX est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 05h28.


 
 
 
 
Partenaires

Hébergement Web