Page 1 sur 1

script BDD trop lourd et lent.

Posté : 15 août 2006, 06:05
par dtom99
Bonjour a tous et merci d'avance à ceux qui m'aideront.

Voici mon script php, qui recopie et traite des informations depuis cette table : http://s11.travian.fr/map.sql

J'explique un peu le fonctionnement de mon code.

La table x_world (voire lien ci dessus), contient des entrées de villages.

- Je recopie cette table dans une table nommée "data_joueurs" (ceci est trés rapide, pas de pb).
- Ensuite je calcule le nombre de villages que posséde un joueur en parcourant toutes les entrées dont l'id correspond au même joueur, et je l'écris bien sur, je met soit à jour les données du village, soit je crée une nouvelle ligne, si elle n'existe pas.

- Je calcule la progression en lisant cette fois depuis la table data_joueurs afin de voire si le village du joueur progresse, régresse ou stagne.

- Je décale le nombre de points du village d'une case, afin d'avoir un historique de son évolution sur 10 jours.


Voilà le soucis c'est que l'opération de comptage des villages est la plus longue, et comme je traite 20 bases à la fois, cela me prend prés de 4h en tout, avec un ordinateur trés bon (amd 64 3000+ 1Go DDR PC3200).

j'ai essayé d'alloué plus de ram à mysql, mais il prend tjrs 12mo en processus, j'ai pourtant mi 128m.

Je précise que j'utilise EASY PHP 1.8, MySQL4, et donc un OS XP SP2.


J'attend de vous des idées d'amélioration du code, afin de gagner sensiblement en temps d'éxécution.

ps : je précise que ces calculs sont fais afin de ne pas gêner les visiteurs de mon futur site, qui devront les faires à la demande...

<?php

/*#####       Paramètres de la base de donnees              #####*/
$host= "localhost"; //Hote
$user= "root"; //Nom de l'utilisateur
$pass= "xxxxx"; //Mot de passe  pour acceder a la base de donnees
$nombreServeursFr=13;
$nombreServeursFr=$nombreServeursFr+1;        
$nombreServeursCom=7;
$nombreServeursCom=$nombreServeursCom+1;
set_time_limit(20000);  //en seconde 20min*60=1200s      
/*#####       Paramètres de la base de donnees              #####*/ 
                

$b=0; 
while($b!=2)
{
if($b==0){$pays="_fr";$nombreServeurs=$nombreServeursFr;}else{$pays="_com";$nombreServeurs=$nombreServeursCom;}
$b++;
$a=1;
while($a!=$nombreServeurs)
{
$base="travian_s"."$a"."$pays"; //Nom de la base de donnees     
$a++;
///////////////////////////////////////////BOUCLE DU CODE/////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
//Verifie si on peut se connecter a la base sql
$connect=mysql_connect($host,$user,$pass) or die ("Impossible de se connecter");
mysql_select_db($base, $connect) or die ("Impossible de selectionner la base de donnees");

/*#####        création des tables        #####*/
$table="globalData";  //données globales
//echo "Table : $table ($base) en cours...."; 
$sql_create = "CREATE TABLE IF NOT EXISTS `$table` (id INT (10) not null AUTO_INCREMENT, villages VARCHAR (255) not null, joueurs VARCHAR (255) not null, date DATE NOT NULL default '0000-00-00', PRIMARY KEY (id))";
$req_create = mysql_db_query($base, $sql_create) or die(mysql_error());
//echo (" OK!<br>"); 

$table ="data_joueurs";  //données personnalisés
$sql_create = "CREATE TABLE IF NOT EXISTS `$table` (idJoueur INT (10) not null,     
 pseudo VARCHAR (255) not null,
 classement INT (10) null, 
 evolClassement VARCHAR (255) null,      
 peuple INT (10) not null,     
 nomAlliance VARCHAR (255) not null,
 idAlliance INT (10) not null,     
 idVillage INT (10) not null,
 nombreVillage INT (10) null,     
 nomVillage VARCHAR (255) not null, 
 population INT (10) not null, 
 pop1 INT (10) null, 
 pop2 INT (10) null, 
 pop3 INT (10) null,     
 pop4 INT (10) null,     
 pop5 INT (10) null,     
 pop6 INT (10) null,     
 pop7 INT (10) null,     
 pop8 INT (10) null,     
 pop9 INT (10) null,     
 pop10 INT (10) null,     
 populationTotale INT (10) null, 
 popT1 INT (10) null,     
 popT2 INT (10) null,     
 popT3 INT (10) null,     
 popT4 INT (10) null,     
 popT5 INT (10) null,     
 popT6 INT (10) null,     
 popT7 INT (10) null,     
 popT8 INT (10) null,     
 popT9 INT (10) null,     
 popT10 INT (10) null,     
 coordX VARCHAR (255) not null, 
 coordY VARCHAR (255) not null, 
 date DATE NOT NULL default '0000-00-00',
 PRIMARY KEY (idVillage))";
$req_create = mysql_db_query($base, $sql_create) or die(mysql_error());
/*#####        fin création des tables        #####*/  
 
 //########### TEMPORAIRE #################// 
//$sql="TRUNCATE TABLE `data_joueurs`"; 
//mysql_db_query($base, $sql) or die(mysql_error()); 

//$sql="TRUNCATE TABLE `x_world`"; 
//mysql_db_query($base, $sql) or die(mysql_error());  
//########### FIN TEMPORAIRE #################//
 
//#################################### A FAIRE ##############################################//
//------> Enregistre les != villages du meme joueurs dans la nouvelle table data_joueurs, ou la met a jour pour
//eviter les doublons.  

$date=date("Y-m-d");
$updateEntries=0;   
$newsEntries=0;
                      
$result = mysql_query ("SELECT * FROM x_world") or die ("Impossible d'executer la requete 50");
while ($row = mysql_fetch_array($result)) {  
 
//Joueur
$idJoueur = $row ["idJoueur"];
$pseudo= $row ["joueur"];   
$peuple = $row ["peuple"];
//Ally
$nomAlliance = $row ["alliance"];
$idAlliance = $row ["idAlliance"];
//Village
$idVillage = $row ["idVillage"];
$nomVillage = $row ["Village"];
$population = $row ["population"]; 
$coordX = $row ["X"]; 
$coordY = $row ["Y"]; 
               

//---> nombre de villages du joueur et points de tous ses villages 
$result02 = mysql_query ("SELECT idVillage, population FROM x_world WHERE idJoueur='$idJoueur'") or die ("Impossible d'executer la requete 56");
$nbVillagesJoueur = mysql_num_rows($result02);
$populationTotale=0;
while ($row03 = mysql_fetch_array($result02)) {
$popVillage = $row03 ["population"];
$populationTotale = $populationTotale+$popVillage;
} 
//


// -------------------->  Ecriture BDD Joueurs !! <---------------//    


////////////// <------ Test existance du village    
$result05=mysql_query ("SELECT * FROM data_joueurs WHERE idVillage='$idVillage'") or die ("Impossible d'executer la requete 137");
$row05 = mysql_fetch_array($result05);
$idVillageBase = $row05["idVillage"];
///////////// <------ Fin du test

//si inexistant alors créer         
if($idVillageBase!="$idVillage"){   
$query = mysql_query ("INSERT INTO data_joueurs (idJoueur,pseudo,classement,peuple,nomAlliance,idAlliance,idVillage,nombreVillage,nomVillage,population,populationTotale,coordX,coordY,date) values ('$idJoueur', '$pseudo', '$classement', '$peuple', '$nomAlliance', '$idAlliance', '$idVillage', '$nbVillagesJoueur', '$nomVillage', '$population', '$populationTotale', '$coordX', '$coordY', '$date')");
$newsEntries++;     
}

//sinon on met à jour
else{
$query = mysql_query ("UPDATE data_joueurs SET nomAlliance='$nomAlliance', idAlliance='$idAlliance', nomVillage='$nomVillage', population='$population', populationTotale='$populationTotale', date='$date' WHERE id='$idVillage'");     
$updateEntries++;
} 
 
//  
// ------------------>  Fin Ecriture BDD Joueurs!! <--------------//    
//

}  
echo("<br>$newsEntries--> Nouvelles entrées");
echo("<br>$updateEntries --> Mises à jour");
echo "<br>Table : $table ($base) en cours.... OK!"; 


//---> classement du joueur
$classement=0;
$idJoueur=0;
$result = mysql_query ("SELECT * FROM data_joueurs ORDER BY populationTotale DESC") or die ("Impossible d'executer la requete 178");                                                     
while ($row = mysql_fetch_array($result)) { 

$idJoueurTMP = $row ["idJoueur"];  

$ok=0;
 
if($idJoueur!=$idJoueurTMP){
$classement++; 
$ok=1;
}

//Joueur
$idVillage = $row ["idVillage"];
$idJoueur = $row ["idJoueur"]; 
$pseudo = $row ["pseudo"];
 
/*
//vérif
if(($classement<11)&($ok==1)){
echo("<br>$classement.&nbsp;$pseudo"); }
*/ 

//---> progression ou régréssion?
$result04=mysql_query ("SELECT * FROM data_joueurs WHERE idVillage='$idVillage'") or die ("Impossible d'executer la requete");
$row04 = mysql_fetch_array($result04);
$ClassementBase = $row04["classement"];

//conditions
if($classement>"$ClassementBase"){
$evolClassement="-"; //régresse
}
if($classement<"$ClassementBase"){
$evolClassement="+"; //progresse
}
if($classement=="$ClassementBase"){
$evolClassement="=";  //stagne
}
//

//données historiques de tous les villages       
$popT1 = $row04["populationTotale"]; 
$popT2 = $row04["popT1"];
$popT3 = $row04["popT2"];
$popT4 = $row04["popT3"];
$popT5 = $row04["popT4"];
$popT6 = $row04["popT5"];
$popT7 = $row04["popT6"];
$popT8 = $row04["popT7"];
$popT9 = $row04["popT8"];
$popT10 = $row04["popT9"];

//données historiques du village     
$pop1 = $row04["population"];
$pop2 = $row04["pop1"];
$pop3 = $row04["pop2"];
$pop4 = $row04["pop3"];
$pop5 = $row04["pop4"];
$pop6 = $row04["pop5"];
$pop7 = $row04["pop6"];
$pop8 = $row04["pop7"];
$pop9 = $row04["pop8"];
$pop10 = $row04["pop9"];


$query = mysql_query ("UPDATE data_joueurs SET classement='$classement', evolClassement='$evolClassement', popT1='$popT1', popT2='$popT2', popT3='$popT3', popT4='$popT4', popT5='$popT5', popT6='$popT6', popT7='$popT7', popT8='$popT8', popT9='$popT9', popT10='$popT10', pop1='$pop1', pop2='$pop2', pop3='$pop3', pop4='$pop4', pop5='$pop5', pop6='$pop6', pop7='$pop7', pop8='$pop8', pop9='$pop9', pop10='$pop10' WHERE idVillage='$idVillage'");  
 
//test delete 
//$query = mysql_query ("UPDATE data_joueurs SET classement='' WHERE idVillage='$idVillage'");      
}

//#################################### FIN DE "A FAIRE" ########################################//
/* 
//------> Recupere le nombre de villages
$result = mysql_query ("SELECT * FROM data_joueurs") or die ("Impossible d'executer la requete 155");
$nbVillages = mysql_num_rows($result);

//------> Recupere le nombre de joueurs
$result = mysql_query ("SELECT * FROM data_joueurs ORDER BY populationTotale DESC") or die ("Impossible d'executer la requete 178");                                                     
while ($row = mysql_fetch_array($result)) { 

$X = $row ["nombreVillage"];  
$nbJoueurs=$nbJoueurs+($X/($X^2)); 
}
echo ("<br>nombre de joueurs: $nbJoueurs");      

 
// -------------------->  Ecriture BDD Données Globales !! <---------------//
$query = mysql_query ("insert into globaldata (villages, joueurs, date) values ('$nbVillages', '$nbJoueurs', '$date')");                                            
// ------------------>  Fin Ecriture BDD Données Globales !!  <--------------//               
 */
//affichage de vérification
//echo ("<br>$monde $pays ==> $nbVillages villages");
//echo ("&nbsp;base $monde $pays faite!");
                                
//////////////////////////////////////////////

/////
$temps = microtime(); // Timestamp actuel + microsecondes
$temps = explode(' ', $temps); // Je sépare la chaine, les deux segments sont retournés dans un array $temps[]
$fin = $temps[1] + $temps[0]; // J'additionne ces deux temps pour avoir le timestamp en microseconde de fin d'execution..
$duree = round(($fin - $debut),6); // Je fais la soustraction des deux temps pour obtenir le temps d'execution.. (Ici arrondi à 6 chiffres après la virgule, vous pouvez modifier cette valeur..)

$dureeMinutes=$duree/60;
echo"</div><div id=footer>\n<br><center> page générée en ". $duree. "s ($dureeMinutes minutes)</div>";


////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

//vide la table pour la prochaine importation
$sql="TRUNCATE TABLE `x_world`"; 
mysql_db_query($base, $sql) or die(mysql_error()); 
}
}

Posté : 15 août 2006, 12:16
par Hubert Roksor
Je n'ai pas tout lu, mais tu peux commencer par des trucs simples, par exemple: utiliser mysql_fetch_assoc() à la place de mysql_fetch_array() (je te laisse cliquer sur les liens pour connaitre la différence). La philosophie est d'en faire le minimum. Seuls les champs dont tu as besoin devraient apparaître dans la clause SELECT (par exemple, tu n'as pas toujours besoin des "IDs").

Autre chose, j'ai remarqué une boucle qui n'a pour seul but que de faire la somme d'une colonne. Tu peux la remplacer par une seule requête:

Code : Tout sélectionner

SELECT SUM(population) AS total FROM x_world WHERE idJoueur = ...
Si tu veux le nombre d'enregistrements correspondant à une requête, utilise COUNT(*). Et en plus tu peux le faire dans la même requête que la précédente:

Code : Tout sélectionner

SELECT COUNT() AS nb, SUM(population) AS total FROM x_world WHERE idJoueur = ...
Dernière chose, à la place de SELECT + UPDATE/INSERT, tu dois pouvoir utiliser REPLACE.

Posté : 16 août 2006, 17:09
par dtom
je regarde déjà pour alleger avec le replace, en esperant qu'il prend en compte les clés a ne pas remplacer.

Posté : 18 août 2006, 06:45
par Invité
voila le soucis de replace, c'est que si il trouve une clé avec deux ID identiques, il va d'abord virer l'ancienne puis rajouter la nouvelle.

mais je voudrais garder certaines informations dans les champs.

Posté : 18 août 2006, 22:03
par dtom
désolé c'était moi au dessus.


le gros soucis de mon script, c'est que j'utilise plusieurs fois des boucles, avec recherche, ce qui est lourd, mais je sait pas comment remplacer ça xD

Posté : 22 août 2006, 02:52
par dtom
up, personne n'a une idée pour pouvoir remplacer en une seule action cette portion de code ?

//
// -------------------->  Ecriture BDD Joueurs !! <---------------//    
//
  
////////////// <------ Test existance du village    
$result05=mysql_query ("SELECT idVillage FROM data_joueurs WHERE idVillage='$idVillage'") or die ("Impossible d'executer la requete 137");
$row05 = mysql_fetch_array($result05);
$idVillageBase = $row05["idVillage"];
///////////// <------ Fin du test
 
//si inexistant alors créer         
if($idVillageBase!="$idVillage"){   
$query = mysql_query ("INSERT INTO data_joueurs (idJoueur,pseudo,peuple,nomAlliance,idAlliance,idVillage,nombreVillage,nomVillage,population,populationTotale,coordX,coordY,date) values ('$idJoueur', '$pseudo', '$peuple', '$nomAlliance', '$idAlliance', '$idVillage', '$nbVillagesJoueur', '$nomVillage', '$population', '$populationTotale', '$coordX', '$coordY', '$date')");
$newsEntries++;     
}

//sinon on met à jour
else{ 
$query = mysql_query ("UPDATE data_joueurs SET idJoueur='$idJoueur', pseudo='$pseudo', peuple='$peuple', nomAlliance='$nomAlliance', idAlliance='$idAlliance', nombreVillage='$nbVillagesJoueur', nomVillage='$nomVillage', population='$population', populationTotale='$populationTotale', date='$date'  WHERE idVillage='$idVillage'");  
$updateEntries++;
} 
  
//  
// ------------------>  Fin Ecriture BDD Joueurs!! <--------------//    
//

}//fin de la boucle