Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD
PHP & SGBD Forum d'entraide sur les SGBD avec PHP. Avant de poster : FAQ BDD, toutes les FAQ PHP, cours BDD et sources BDD
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 14/03/2006, 15h47   #1
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
Par défaut [Optimisation] SQL et boucles

Salut a tous !

Alors, voici ma situation :

j'ai une fonction qui me retourne le resultat d'une requete dans un tableau associatif, dont les clés sont les champs de ma table ...

J'ai ensuite d'autres fonctions qui font un traitement sur ce tableau ...
Dans un certains cas, mon tableau contient 20 clés pour 10912 valeurs par clé.

Le probleme, c que pour ce cas, mon script est beaucoup trop long.

En faisant une fonction de test, qui se place dans mon cas :


Code :
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
 
function testBoucles()
{
 
//pour chaque ligne
	for($i=0;$i<10912;$i++)
	{
 
		$strmachin.="machin \n";
//pour chaque clé
		for($j=0;$j<20;$j++)
		{
			$strmachin.="machin \n";
 
//boucle de traitement test pour clé, ligne courante
			for ($k=0;$k<10;$k++)
			{
				$strmachin.="machin \n";
				getArraySqlValue($aPhp_ResultSql,$i,$j);
			}
		}
 
	}
	echo $strmachin;
}
Dans ces boucles imbriquées, j'appelle uniquement la fonction getArraySqlValue();



Code :
1
2
3
4
5
6
7
8
9
10
11
12
function getArraySqlValue($aPhp_ResultSql,$intSqlLine,$intSqlCol)
{
 
	global $glb_aSqlKeyCols;
 
	$colId=$glb_aSqlKeyCols[$intSqlCol];
 
	$strContenuCel=$aPhp_ResultSql[$colId][$intSqlLine];
 
 
	return $strContenuCel;
}

Je fais un die juste apres la fonction testBoucle, mon script met 41 sec a s'executer ...

Pensez vous que c normal, et auriez vous des idées d'optimisation ?


Merci bien pour votre aide !

@+.
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/03/2006, 19h01   #2
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
en passant directement par le tableau dans ma fonction testBoucle en faisant :

Code :
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
 
function testBoucles()
{
 
//pour chaque ligne
   for($i=0;$i<10912;$i++)
   {
 
      $strmachin.="machin \n";
//pour chaque clé
      for($j=0;$j<20;$j++)
      {
         $strmachin.="machin \n";
 
//boucle de traitement test pour clé, ligne courante
         for ($k=0;$k<10;$k++)
         {
            $strmachin.="machin \n";
            $machin=$aPhp_ResultSql['Schema_Name'][$i]; 
         }
      }
 
   }
   echo $strmachin;
}
C'est encore plus long ... avez vous deja eu ce cas ? pensez vous que c normal ? c vrai que ca fait beaucoup d'itérations ...
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/03/2006, 19h10   #3
Membre émérite
 
Avatar de macbook
 
Inscription : février 2006
Messages : 840
Détails du profil
Informations forums :
Inscription : février 2006
Messages : 840
Points : 924
Points : 924
Je ne pige pas trop ce que tu cherches à faire, mais avec tes trois boucles imbriquées tu arrives à 2 182 400 itérations en 41 secondes, ce qui fait 53230 itérations à la seconde. Pas mal comme rendement.

A mon avis il faut que tu revois ta procédure. Ce nombre 10912 il sort d'où ?
__________________
Consultant idéaliste.
macbook est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/03/2006, 19h53   #4
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
Citation:
Envoyé par macbook
Ce nombre 10912 il sort d'où ?
Ca, c'est le nombre d'entrée que me genere l'execution de la requete ...

La fonction qui l'execute me renvoi un tableau du style :

Code :
1
2
3
4
5
6
7
8
9
 
$tabSql : 
           ['Schema_Name']
                                    0=>"Ev_Boss'
                                    1=>'Ev_Boss' ... 
 
           ['Field_Name']
                                    0=>"machin"
                                    1=>"truc" ...
10912 ca veut dire que ma requete m'a renvoyé 10912 nom de champs ...

Ensuite, ce que j'essaye de faire, c travailler sur ce tableau pour generer un tableau HTML avec des rowspan ...

Donc, pour chaque ligne de mon tableau, pour chaque colone, je cherche le nombre de repetition de la valeut en cours ...
D'ou mes 3 boucles ...

En n'utilisant pas mon tableau dans la fonction de test, donc en faisant ceci :

Code :
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
 
 
function testBoucles()
{
 
//pour chaque ligne
   for($i=0;$i<10912;$i++)
   {
 
      $strmachin.="machin \n";
//pour chaque clé
      for($j=0;$j<20;$j++)
      {
         $strmachin.="machin \n";
 
//boucle de traitement test pour clé, ligne courante
         for ($k=0;$k<10;$k++)
         {
            $strmachin.="machin \n";
         }
      }
 
   }
   echo $strmachin;
}
On arrive a a peu pres 10s ... c deja beaucoup mieux !

je vois pas trop pourquoi ca prends 40sec de plus en faisant :
Code :
[$machin=$aPhp_ResultSql['Schema_Name'][$i];
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/03/2006, 20h01   #5
Membre émérite
 
Avatar de macbook
 
Inscription : février 2006
Messages : 840
Détails du profil
Informations forums :
Inscription : février 2006
Messages : 840
Points : 924
Points : 924
Je ne sais pas si c'est à destination d'utilisateur, mais même 10 secondes c'est énorme.
__________________
Consultant idéaliste.
macbook est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/03/2006, 20h58   #6
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
c a destination d'utilisateur, et oui 10 sec c deja enorme !

C'est pour ca qu'il faut optimiser, bon la faut dire que la requete renvoit enormement de lignes ...
D'habitude, elle renvoie pas plus de 1000 lignes ...

Je vais peut etre devoir changer d'algo ...
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 09h37   #7
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
Salut !

C'est bete, parce que ya vraiment un seul cas ou ma requete me renvoit un tableau aussi enorme ...

Si je divise ce tableau, en 2 ou en 3, vous pensez que le temps d'execution sera reduit ??

Merci !

@+.
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 10h00   #8
Membre éclairé
 
Avatar de XtofRoland
 
Inscription : août 2005
Messages : 361
Détails du profil
Informations forums :
Inscription : août 2005
Messages : 361
Points : 340
Points : 340
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function testBoucles(){ 
 
//pour chaque ligne 
   for($i=0;$i<10912;$i++) { 
      $strmachin.="machin \n"; 
      for($j=0;$j<20;$j++) { 
         $strmachin.="machin \n"; 
         for ($k=0;$k<10;$k++) { //a quoi sert ton k?????
            $strmachin.="machin \n"; 
			global $glb_aSqlKeyCols; 
			$strContenuCel=$aPhp_ResultSql[$glb_aSqlKeyCols[$j]][$i]; 
         } 
      } 
 
   } 
   echo $strmachin; 
}
eviter de passer par des appels de fonction peut pe accelerer,
a quoi sert ta boucle k????
ne peux tu utiliser array_walk plutot qu'un for?
passer par des variables intermediaires bouffe pe ta memoire.
par contre en fin de boucle tes string doivent etre assez long, et cela ralentit eventuellement l'execution...


juste qq idée a tester ;-)

si tu doit mettre tes donnée ds un tableau tu peu penser a des methodes alternative
imaginons une ligne d'un tableau(apres un serialize)
12;12;15;17;16;13
tu fait un ereg replace des ; par
et tu obtiend deja :
12</td><td>12</td><td>15</td><td>17</td><td>16</td><td>13
__________________
Le but de tout developpeur OO est de devenir une référence.
Mon avatar est un ambigramme, les curieux peuvent le retourner ;-)
Aider <> Faire a la place de!!!
XtofRoland est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 10h09   #9
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
ma fonction de test, c ca maintenant :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
function testBoucles($aPhp_ResultSql)
{
	//echo "<pre align=left>aPhp_ResultSql: <br>";print_r($aPhp_ResultSql);echo "</pre>";
 
	for($i=0;$i<10912;$i++)
	{
		for($j=0;$j<20;$j++)
		{
			for ($k=0;$k<10;$k++)
			{					
				$a=getArraySqlValue($aPhp_ResultSql,$i,$j);
			}
		}
	}
	//echo $a;
}

Ca, ca met 21 sec ... enorme ! Mais en meme temps pas tres etonnant vu le nombre d'iterations ...


Ma boucle k sert a determiner le nombre de repetition d'une valeur pour une ligne/col ... (dans mon vrai script).


Merci en tout cas !

@+.
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 10h22   #10
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 720
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 720
Points : 17 355
Points : 17 355
Salut

C'est peut-être dans ce genre de situations que l'on peut gratter quelques secondes en changeant $i++ par ++$i...
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 10h29   #11
Membre éclairé
 
Avatar de XtofRoland
 
Inscription : août 2005
Messages : 361
Détails du profil
Informations forums :
Inscription : août 2005
Messages : 361
Points : 340
Points : 340
file ton vrai script si tu veux qu'on optimise...

que peut on faire avec ca:

function testBoucles($aPhp_ResultSql)
{
//echo "<pre align=left>aPhp_ResultSql: <br>";print_r($aPhp_ResultSql);echo "</pre>";

for($i=0;$i<10912;$i++)
{
for($j=0;$j<20;$j++)
{
for ($k=0;$k<10;$k++)
{
$a=getArraySqlValue($aPhp_ResultSql,$i,$j);
}
}
}
//echo $a;
} ?

moi si tu me file ca a optimiser je te rend ca :

function testBoucles($aPhp_ResultSql)
{
print_r($aPhp_ResultSql)."</pre>";
for($i=0;$i<10912;$i++)
for($j=0;$j<20;$a=getArraySqlValue($aPhp_ResultSql,$i,$j++))

}
__________________
Le but de tout developpeur OO est de devenir une référence.
Mon avatar est un ambigramme, les curieux peuvent le retourner ;-)
Aider <> Faire a la place de!!!
XtofRoland est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 10h35   #12
Rédacteur
 
Avatar de Yogui
 
Homme Guillaume Rossolini
Directeur technique
Inscription : février 2004
Messages : 13 720
Détails du profil
Informations personnelles :
Nom : Homme Guillaume Rossolini
Localisation : France

Informations professionnelles :
Activité : Directeur technique

Informations forums :
Inscription : février 2004
Messages : 13 720
Points : 17 355
Points : 17 355
XtofRoland : Ce n'est pas de l'optimisation, c'est de l'obfuscation de code :/
Tu concatènes avec print_r() ?
Pourrais-tu réutiliser la balise code, je te prie ? C'est tellement plus lisible avec... Merci !
__________________
Mes articles - Zend Certified Engineer (PHP + Zend Framework)
Ressources PHP - Ressources Zend Framework
Yogui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 10h37   #13
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
voici, j'ai mis le minimul qui fait deja tout ramer ...


Code :
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
 
	for($i_SqlLine=0; $i_SqlLine<$glb_intNbSqlLines; $i_SqlLine++)
	{	
 
		$intHtmlLine=newHtmlLine($aPhp_Html,$intHtmlLine,$aProperties);
 
		$intHtmlCol=-1;
		for($i_SqlCol=0; $i_SqlCol<$glb_intNbSqlCols; $i_SqlCol++)
		{
			//recuperation du nom de la col suivante pour le tableau SQL
			$colId=$glb_aSqlKeyCols[$i_SqlCol+1];
 
			$intHtmlCol++;
			//si on a depassé le rowspan pour la colonne actuelle
 
			//test si nouvelle cellule
			{
 
				$strSqlContentCel 	= getArraySqlValue($aPhp_ResultSql,$i_SqlLine,$i_SqlCol);
 
				//nb de repetition de la nouvelle cellule
				$intSqlRowSpan=getArraySqlValueRepeat($aPhp_ResultSql,$i_SqlLine,$i_SqlCol);
			}
		}
	}
 
 
function getArraySqlValueRepeat($aPhp_ResultSql,$intSqlLine,$intSqlCol)
{
	global $glb_aSqlCelSaveProp;
	global $glb_intNbSqlLines;
 
	if($intSqlCol == 0)	//si on est a la 1ere colonne
		$intSqlBorneSupPrecedent = $glb_intNbSqlLines;
	else	//si on est a une autre colonne que la 1ere
		//borne superieur = interval precedent
		$intSqlBorneSupPrecedent = $glb_aSqlCelSaveProp[$intSqlCol-1]['INT_LIMIT_UPPER_PREVIOUS'] ;
 
	$intRowSpan=0;
	$strContentCel=getArraySqlValue($aPhp_ResultSql,$intSqlLine,$intSqlCol);
 
	//recherche pour l'interval precedent
	for($j_interval=$intSqlLine;$j_interval<$intSqlBorneSupPrecedent;$j_interval++)
	{		
		//test de repetition de la valeur
		if(getArraySqlValue($aPhp_ResultSql,$j_interval,$intSqlCol)==$strContentCel)
			$intRowSpan++;
		else break;
	}
	return $intRowSpan;
}
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 11h09   #14
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
m'enfin meme la je vois pas trop quoi optimiser ... mis a part en changeant d'algo et encore ...
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 13h16   #15
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
Le probleme, c que j'ai besoin de la 3è boucle !

Je vois pas trop comment faire autrement ...

Et si je divisais le tableau sur lequel je boucle en plusieurs parties lorsqu'il est enorme comme ca ??
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 13h26   #16
Expert Confirmé Sénior
 
Avatar de Mr N.
 
Inscription : septembre 2004
Messages : 5 421
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 5 421
Points : 5 835
Points : 5 835
Tu affiches un tableau html de 10000 lignes ?
Mr N. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 13h43   #17
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
Au depart, j'ai un tableau generé par une requete, de 20 colonnes pour 10912 lignes...

Je boucle dessus, pour en faire un tableau PHP ($tabPhp) qui servira pour l'affichage ...

ensuite, je boucle sur $tabPhp pour afficher les lignes et les cellules de mon tableau HTML.

Donc oui, j'affiche un tableau HTML de 10 000 lignes ...
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 13h52   #18
Expert Confirmé Sénior
 
Avatar de Mr N.
 
Inscription : septembre 2004
Messages : 5 421
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 5 421
Points : 5 835
Points : 5 835
Est-ce que tu penses que l'utilisateur a vraiment besoin d'avoir 10000 lignes d'un coup ?
Pourquoi n'utiliserais-tu pas la pagination, à savoir n'afficher que 10 résultats par page comme le fait google par exemple.
Je sais que ca ne résoud pas directement tes problèmes de performances, mais c'est un moyen de contournement qui a objectivement toute son utilité.

Ensuite, es-tu sur que c'est ton code php qui plombe les performances et pas la requête sql ? Est ce que tu as utilisé l'exemple de la page http://php.net/microtime pour voir quel partie de ton code prenait le plus de temps ?
Exemple:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function microtime_float()
{
  list($usec, $sec) = explode(" ", microtime());
  return ((float)$usec + (float)$sec);
}
...
$boucle_externe = microtime_float();
for ($i) {
   $boucle_interne = microtime_float();
   for ($j) {
   }
   echo $i." Boucle interne = ".(microtime_float()-$boucle_interne)."<br>";
}
echo "Boucle externe = ".(microtime_float()-$boucle_externe)."<br>";
Mr N. est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 14h13   #19
Nouveau Membre du Club
 
Inscription : décembre 2003
Messages : 223
Détails du profil
Informations forums :
Inscription : décembre 2003
Messages : 223
Points : 25
Points : 25
Citation:
Envoyé par Mr N.
Ensuite, es-tu sur que c'est ton code php qui plombe les performances et pas la requête sql ? Est ce que tu as utilisé l'exemple de la page http://php.net/microtime pour voir quel partie de ton code prenait le plus de temps ?
Ouais, j'ai utilisé cette fonction, et rien qu'avec le code ci dessous, ca prends deja + de 30s ...


Code :
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
 
for($i_SqlLine=0; $i_SqlLine<$glb_intNbSqlLines; $i_SqlLine++)
   {   
 
      $intHtmlLine=newHtmlLine($aPhp_Html,$intHtmlLine,$aProperties);
 
      $intHtmlCol=-1;
      for($i_SqlCol=0; $i_SqlCol<$glb_intNbSqlCols; $i_SqlCol++)
      {
         //recuperation du nom de la col suivante pour le tableau SQL
         $colId=$glb_aSqlKeyCols[$i_SqlCol+1];
 
         $intHtmlCol++;
         //si on a depassé le rowspan pour la colonne actuelle
 
         //test si nouvelle cellule
         {
 
            $strSqlContentCel    = getArraySqlValue($aPhp_ResultSql,$i_SqlLine,$i_SqlCol);
 
            //nb de repetition de la nouvelle cellule
            $intSqlRowSpan=getArraySqlValueRepeat($aPhp_ResultSql,$i_SqlLine,$i_SqlCol);
         }
      }
   }
 
 
function getArraySqlValueRepeat($aPhp_ResultSql,$intSqlLine,$intSqlCol)
{
   global $glb_aSqlCelSaveProp;
   global $glb_intNbSqlLines;
 
   if($intSqlCol == 0)   //si on est a la 1ere colonne
      $intSqlBorneSupPrecedent = $glb_intNbSqlLines;
   else   //si on est a une autre colonne que la 1ere
      //borne superieur = interval precedent
      $intSqlBorneSupPrecedent = $glb_aSqlCelSaveProp[$intSqlCol-1]['INT_LIMIT_UPPER_PREVIOUS'] ;
 
   $intRowSpan=0;
   $strContentCel=getArraySqlValue($aPhp_ResultSql,$intSqlLine,$intSqlCol);
 
   //recherche pour l'interval precedent
   for($j_interval=$intSqlLine;$j_interval<$intSqlBorneSupPrecedent;$j_interval++)
   {      
      //test de repetition de la valeur
      if(getArraySqlValue($aPhp_ResultSql,$j_interval,$intSqlCol)==$strContentCel)
         $intRowSpan++;
      else break;
   }
   return $intRowSpan;
}

Pour la pagination, c'est une bonne idée ... mais ca ca concerne l'affichage ...

il faudrait deja que j'optimise le temps d'execution du traitement !
schnito est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/03/2006, 14h17   #20
Expert Confirmé Sénior
 
Avatar de Mr N.
 
Inscription : septembre 2004
Messages : 5 421
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 5 421
Points : 5 835
Points : 5 835
Ben pas forcément, si tu ne récupères que 10 éléments de ta bd (grace à LIMIT sous mysql par exemple), ca ira forcément plus vite, affichage ou pas.
Mr N. 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 03h53.


 
 
 
 
Partenaires

Hébergement Web