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

PHP & Base de données Discussion :

Insertions et mise à jour SQL à partir d'un fichier texte lourd : optimiser un script [MySQL]


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Janvier 2008
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 13
    Par défaut Insertions et mise à jour SQL à partir d'un fichier texte lourd : optimiser un script
    Bonjour,

    j'ai une base de données compilée 4D de laquelle j'extrais régulièrement des données, pour mettre à jour une base MySQL.

    Le fichier d'export en .txt pèse env. 5 Mo pour 37000 lignes d'enregistrement comme celle-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AAAA7520;1;ROBERT;Toto;17 AVENUE FONTENAILLE;BAT.B;26100;VALENCE;;21/01/02;toto.ex@wanadoo.fr;00/00/00;;1;24/12/2002;Faux;Faux;NR
    Mon script uploade le .txt, formate et compare les données, et met éventuellement à jour la base MySQL.

    MA QUESTION porte sur la méthode: en effet lorsque je faisais le boulot en une seule passe, j'avais des problèmes de temps d'execution et tutti quanti.

    J'ai donc mis en place le système suivant: je découpe le gros fichier en x fichiers plus petits (de 1500 lignes par ex.) puis les traite un par un. Ca se passe mieux mais c'est encore hypra long et prend 99% des ressources pendant plusieurs mn.

    Qu'est-ce qui dans mon script est si gourmand en ressources ?

    Peut-être aurais-je dû faire autrement ? Est-ce plus efficace par ex de preparer les update et les insert et de les executer seulement à la fin du traitement?

    Ci-dessous une synthèse du script (j'ai voulu éviter de poster une tartine de code indigeste). Le script complet est en PJ pour les courageux.

    Merci à ceux qui voudront bien s'y pencher et commenter.

    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
    <?php require('include/fonction.php');
     
    //DECLARATION DES VARIABLES	
     
    			//some code	
     
    //UPLOAD
     
    			//some code	
     
    //CONVERSION DU FICHIER EN X FICHIERS DE 1500 LIGNES
     
    			//some code	
     
    //IMPORT DU CONTENU DE CHAQUE FICHIER CREE DANS LA DB 
    	$dir = opendir($dossier); 
     
    	while($file = readdir($dir)) {
    		if($file != '.' && $file != '..' && !is_dir($dossier.$file)) 	{
     
    			//TRAITEMENT DE CHAQUE FICHIER
    			$arrayTxt = file($dossier.$file);
    			for( $i=0; $i<count($arrayTxt); $i++ ) {
     
    				$arrayProd[$i] = explode(";",$arrayTxt[$i]);
     
    				//FORMATAGE DES DONNEES
    				$code = addslashes( trim( $arrayProd[$i][0] )) ;  
    				$tel = eregi_replace("[^0-9]", "", str_replace('+', '00', $arrayProd[$i][12] ) ); 
     
    						//etc... 				
     
    				//COMPARAISON DES DONNEES AVEC LA BASE MYSQL: ON DOIT VERIFIER DANS L'ORDRE CERTAINES CORRESPONDANCES
     
    				//CAS N°1 ?
    				$c = returnChamp(' `code_4D`', 'client' , 'code_4D ="'.$code.'"'); //SELECT ...FROM ... WHERE ...
    				if($c[0]) {
     
    					//UPDATE DATABASE
     
    				}
     
    				else {//CAS N°2 ?
    					$c2 = returnChamp('clientid', 'client', 'email <> "" AND email ="'.$email.'" AND code_4D =""' ); //SELECT ...FROM ... WHERE ...
    					if($c2[0]) {
     
    						//UPDATE DATABASE
     
    					}
    					else {//CAS N°3 ?
    						$c3 = returnChamp('`clientid` , `email`' , 'client', 'nom ="'.$nom.'" AND prenom = "'.$prenom.'" AND ( tel = "'.$tel.'" OR dateNaiss = "'.$dateNaiss.'" OR ( cp = "'.$cp.'" AND ville = "'.$ville.'"  ) )');//
    						if($c3[0]) {
     
    							//UPDATE DATABASE
     
    						}
    						else {//CAS N°4 ?
    							$c4 = returnChamp('clientid', 'client', 'nom ="'.$nom.'" AND prenom = "'.$prenom.'"');
    							if($c4[0]) {
     
    								//UPDATE DATABASE
     
    							}
    							else {
    									//INSERTION NVO CLIENT
    							}
    						}
    					}
    				}
    			}
    		}
    	}
    	closedir($dir);
     
    	//SUPPRESSION DES FICHIERS 
    ?>
    Fichiers attachés Fichiers attachés

  2. #2
    Membre chevronné
    Inscrit en
    Septembre 2006
    Messages
    685
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 685
    Par défaut
    C'est clair que si tu fais une requête par ligne, ça fera 37 000 requêtes

    Normal que ce soit long.

    Concatènes et fais une seule et unique requête à la fin.

    INSERT INTO(..,.. ,.., ..) VALUES(xxx), (yyyy), etc...

  3. #3
    Membre averti
    Inscrit en
    Janvier 2008
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 13
    Par défaut
    Merci. c'est en forgeant ...

    Je vais tester en concaténant les insertions. Mais comme j'ai une grande majorité de update, je crains que cette modif ne change guère la donne ?

    Et pour les update je ne vois pas comment concatener? Sachant qu'on a chaque fois:

    UPDATE table SET champ = $var , champ2 = $var2, etc... WHERE conditions changeantes

    Existe t'il une autre syntaxe?

    Je reprendrai le fil demain, car je quitte le burô . Merci

  4. #4
    Membre chevronné
    Inscrit en
    Septembre 2006
    Messages
    685
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 685
    Par défaut
    Non, pour les updates, tu seras contraint de les faire un à un, pas d'autres solutions.

  5. #5
    jnore
    Invité(e)
    Par défaut
    Citation Envoyé par Xunil Voir le message
    C'est clair que si tu fais une requête par ligne, ça fera 37 000 requêtes

    Normal que ce soit long.

    Concatènes et fais une seule et unique requête à la fin.

    INSERT INTO(..,.. ,.., ..) VALUES(xxx), (yyyy), etc...
    37000 requêtes ce n'est rien, je traite des fichiers bien plus volumineux.
    Dans son cas une connection permanente est nécessaire.

    Personnellement, je n'aurais pas découpé le fichier.
    Je l'aurais analysé d'un seul coup. Par contre j'aurais envoyé mes requetes au serveur par batch de 100 (100 updates par 100 updates).

  6. #6
    Membre chevronné
    Inscrit en
    Septembre 2006
    Messages
    685
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 685
    Par défaut
    Citation Envoyé par jnore Voir le message
    37000 requêtes ce n'est rien, je traite des fichiers bien plus volumineux
    Rien 37000 requêtes ?

    On ne doit pas avoir la même conception du rien.

  7. #7
    jnore
    Invité(e)
    Par défaut
    Citation Envoyé par Xunil Voir le message
    Rien 37000 requêtes ?

    On ne doit pas avoir la même conception du rien.
    Bien sûr que ce n'est rien, pour un SGBD digne de ce nom, c'est une bricole.
    Je viens de faire un script presque identique au sien et j'en suis à plus de 100 000 lignes sous postgres...et là encore ce n'est rien.

    Il faut savoir tout de même que les sgbd sont faits pour ca !

  8. #8
    Membre averti
    Inscrit en
    Janvier 2008
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 13
    Par défaut
    Citation Envoyé par jnore Voir le message
    Par contre j'aurais envoyé mes requetes au serveur par batch de 100 (100 updates par 100 updates).
    Ok Jnore, je suis preneur. Je gère ça comment dans mon script ?

  9. #9
    jnore
    Invité(e)
    Par défaut
    Citation Envoyé par zorbalegrec Voir le message
    Ok Jnore, je suis preneur. Je gère ça comment dans mon script ?
    Je n'ai pas le temps ce soir, je reviens te donner un bout de code demain.
    En attendant essaye de ton coté:
    1) en ouvrant une connection permanente
    2) en scrutant tout ton fichier via une boucle.
    3) dans ta boucle concaténer dans une variable 100 requetes à la fois.
    4) faire une mysql_query de tes 100 requetes
    5) continuer l'analyse et refaire une concaténation de 100 requetes.
    6) rebelote, mysql_query des 100 requetes
    .......
    jusqu'à la fin du fichier

    Cela devrait améliorer tes perfs, mais pour autant cela ne fera pas de miracle.
    Ce qu'il serait intéressant, c'est de nous dire le temps d'execution de ton script...à la louche ..on est pas à la seconde près.

  10. #10
    Membre averti
    Inscrit en
    Janvier 2008
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Janvier 2008
    Messages : 13
    Par défaut
    Citation Envoyé par jnore Voir le message
    Cela devrait améliorer tes perfs, mais pour autant cela ne fera pas de miracle. Ce qu'il serait intéressant, c'est de nous dire le temps d'execution de ton script...à la louche ..on est pas à la seconde près.
    Merci pour ces précisions. Je ne vais malheureusement pas pouvoir tester ces jours-ci car je pars en congés et je vais essayer de décrocher du clavier qq jours .
    Mais c'est bien d'un miracle dont j'ai besoin, car on n'est plus à qq secondes près dans mon cas : avant tentative d'optimisation, je fais tourner mes 37.000 lignes en 4mn environ !!!

    D'où ce post! M'étant formé sur le tas, voire sur le tard, je me doute bien que la même OP bien écrite devrait s'effectuer en ... 20 secondes ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 15/09/2018, 22h38
  2. Mise à jour table à partir sous-formulaire
    Par Daniel MOREAU dans le forum Access
    Réponses: 6
    Dernier message: 19/05/2006, 09h26
  3. Mise à jour a partir d'un autre formulaire
    Par xboulney dans le forum Access
    Réponses: 8
    Dernier message: 28/02/2006, 21h55
  4. Mise à jour Pro à partir de licence Etudiant ?
    Par Neilos dans le forum C++Builder
    Réponses: 3
    Dernier message: 15/11/2005, 16h03
  5. Insertion ou mise à jour impossible...
    Par kobe dans le forum Bases de données
    Réponses: 6
    Dernier message: 01/08/2005, 08h37

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