Améliorer les performances du script PHP

Fermé
merchou - 12 mars 2014 à 12:41
 merchou - 12 mars 2014 à 16:37
Bonjour à tous !

J'ai mon code qui permet:

Ouvrir un fichier texte ayant la structure suivante:




23733000227
23733000228
23733000229
23733000230
23733000231
23733000232




**Le fichier a plus de 20 000 lignes**




1- )

je dois prendre chacun de ces nombres et comparer ses 7 derniers chiffres avec les 7
derniers chiffres de chacun des nombres de la première colonne (IMSI) de la table de ma
Base de données MySQL ci-dessous:




--(IMSI)----------------------(MDN)

624030743830000 23733013285
624030743830001 23733013286
624030743830002 23733013287
624030743830004 23733013288
624030743830005 23733013289
624030743830006 23733013290




**Ma table a 500 000 Lignes**




2- )

S'il y'a 1 ( il est unique s'il existe), il le récupère (IMSI) et récupère aussi le nombre qui se
trouve sur la même ligne (MDN) à deuxième colonne et affiche les trois:

- Nombre de départ

- IMSI trouvé semblable ( nombre de la colonne IMSI donc les 7 derniers chiffres sont
semblables aux 7 derniers chiffres du nombre contenu dans le fichier texte)

- MDN (nombre de la colonne MDN) de la même ligne que l'IMSI trouvé semblable au
nombre de départ.


Mon code fonctionne, il fait le travail attendu. Mais le temps d'exécution est extrêmement long **plus de 30 minutes**.

Voici mon script:




         	<?php	

set_time_limit(0);

//Connexion à la BD
mysql_connect('localhost','root','');
mysql_select_db('gestnum');

//On ouvre le fichier en question (en lecture seule)
$handle = fopen("fichiernum.txt", "r");
$i=0;

echo '<table align=" justify" border = 2 valign = middle>';
//on parcours tout le fichier (en faisant croire qu'il s'agit d'un csv pour faciliter le traitement)
while ($data = fgetcsv($handle, 10000, ",")) 
	  {

//on ne récupère que les 7 derniers caractères de chaque ligne avec la fonction substr
	$rest = substr($data[0],-7);

//On établie une requéte qui ne remonte que les MDN finissant par les 7 derniers chiffre de notre $rest. Un seul résultat remonte donc...
$sql = mysql_query('SELECT * FROM  'coordab' WHERE  'IMSI' LIKE  "%'.$rest.'"');
$result =mysql_fetch_array($sql);
$i++;
 
//on affiche les résultats demandés
echo '<tr>';
echo '<th>'.$i.'</span>'.'</th>';
echo '<th>'.$data[0].'</th>';
echo '<th>'.$result['IMSI'].'</th>';
echo '<th>'.$result['MDN'].'</th>';
echo '</tr>';
    }
echo '</table>';
//On ferme le fichier
fclose($handle);
echo'</div>';

?>




S'il vous plait aidez moi à optimiser mon script pour réduire ce temps d'exécution.
Ou bien montrez moi une autre méthode plus performante pour faire le même travail.

Merci d'avance.
A voir également:

3 réponses

flokocha Messages postés 1510 Date d'inscription lundi 8 mars 2004 Statut Membre Dernière intervention 10 octobre 2015 281
Modifié par flokocha le 12/03/2014 à 13:31
Salut,

Ce qui est coûteux dans ton script, c'est le fait de réaliser en boucle une requête basée sur un like.

La solution que je te propose, c'est de stocker directement dans ta base l'information correspondant aux 7 derniers chiffres des IMSI contenus dans ta table. Cela peut se faire par exemple via une nouvelle colonne dans la table qui contient les IMSI et les MDN, ou dans une table à part qui ferait la relation entre ces 7 derniers chiffres et un index de ta table d'origine, et qui pourrait être alimentée automatiquement par un trigger.

Ainsi tu te passes de ces like très coûteux, ce qui est déjà un premier gain considérable.

Pour aller plus loin, tu peux aussi te passer de ta boucle. Pour cela tu peux loader ton fichier en base dans une table dédiée, via l'intruction mysql LOAD DATA LOCAL INFILE. Soit en le formatant au préalable en local pour lui ajouter une colonne ne contenant que les 7 derniers chiffres de ton IMSI, ou soit à nouveau en créant un trigger en base qui ajoute cette information automatiquement à chaque insertion.

Il te suffira ensuite de tout récupérer en une seule requête, en réalisant une jointure entre tes deux tables.

PS : Une autre solution pourrait être d'effectuer l'opération strictement inverse : c'est à dire qu'au lieu de tout rassembler sur ta base pour pouvoir réaliser ta jointure en une seule fois, tu rassemblerais toutes tes infos en local pour pouvoir réaliser cette jointure. La logique est la même, mais les outils à employer seront différents.
1
Merci pour votre réponse.

J'ai opté pour votre approche, je peux insérer les 7 derniers chiffres de chaque nombre de mon fichier texte dans une table de traitement.
Maintenant comment je peux faire pour récupérer les IMSI dont les 7 derniers chiffres sont semblables à ces chiffres de la table de traitement ainsi que les MDN de correspondants à ces IMSI.

S'il vous plait aidez moi, je suis nouveau en php. Je ne connais pas.
Merci d'avance.
0
Maintenant comment afficher les résultats ?
Voici ce que j'ai fait :

 
          <?php 

set_time_limit(0);

try
{
 $bdd = new PDO('mysql:host=localhost;dbname=gestnum', 'root', '');
}
catch(Exception $e)
{
        die('Erreur : '.$e->getMessage());
}

$reponse = $bdd->query('SELECT 
    IMSI, 
    MDN, 
    ESN1
FROM 'coordab' r
    INNER JOIN 'updateesn1' i ON RIGHT(r.'IMSI', 7) = RIGHT(i.'ESN1', 7)');

while ($donnees = $reponse->fetch())
{
 echo $donnees['ESN1'] . ' appartient à ' . $donnees['IMSI'] . '<br />';
}

$reponse->closeCursor();

?>


Voici l'erreur qu'il m'affiche:

 ! ) Fatal error: Call to a member function fetch() on a non-object in C:\wamp\www\etudephp\recyclage.php on line 21



La colonne ESN1 de la table updateesn1 est bien rempli ainsi que les colonnes IMSI et MDN de coordab.

Comment faire pour visualiser les resultats ?

S'il vous plait aidez moi encore.
Merci.
0