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 :

Optimisation de scripts PHP/MySQL [Débat]


Sujet :

PHP & Base de données

  1. #221
    Membre actif
    Inscrit en
    Janvier 2004
    Messages
    242
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 242
    Points : 271
    Points
    271
    Par défaut
    Citation Envoyé par Kioob
    Citation Envoyé par chaced
    Donc c'est bien d'optimiser a mort le code, faudrait aussi que ça soit le cas du coté du serveur
    yep, mais ça c'est bien souvent l'hebergeur qui le controle.

    Et puis sur un truc codé comme un goret, le cache d'OpCode ne changera pas grand chose : phpBB est lent qu'eAccelerator soit installé ou non.
    Je sens un bon gain en perf, mais j'ai un forum Skyomatic, pas de phpbb

  2. #222
    Membre averti Avatar de XtofRoland
    Profil pro
    Inscrit en
    Août 2005
    Messages
    357
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 357
    Points : 392
    Points
    392
    Par défaut Re: Optimisation de scripts Php/MySQL
    Citation Envoyé par ermelir
    Citation Envoyé par DgG
    A vous maintenant de donner vos astuces, ou de poser des questions.
    - je rajouterais unset($objet) lorsque l'on utilise des objets
    - j'ai aussi pu constater que pour des requetes compliquées le fait de liberer le resultset accelerait considerablement le script , la toujours avec unset
    Il me semble qu'un objet est libéré automatiquement a sa derniere utilisation...
    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!!!

  3. #223
    Membre expérimenté
    Homme Profil pro
    /
    Inscrit en
    Février 2003
    Messages
    433
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : /

    Informations forums :
    Inscription : Février 2003
    Messages : 433
    Points : 1 604
    Points
    1 604
    Par défaut
    Une optimisation qui peut également apporter d'énorme gain de temps d'exéctution lors de nombreuses requetes de selection dans une base de donnée et la mise en cache des résultats dans un fichier local. Le gain n'est évidemment sensible que si les données sélectionnées évoluent peu au cours du temps. Cette astuce dans sa forme actuelle est toutefois à employer avec précaution car tant que le fichier cache n'aura pas été supprimer, cela masquera les données réellement présentes dans la base.
    Dans mon cas, il s'agit d'une gallerie photo. Si elle est mise à jour toutes les semaines c'est énhooooorme .
    Pour mesurer l'ecart de performences, j'ai utilisé le bench fourni par iubito et effectué 5000 itérations
    Voici les résultats que j'ai obtenu
    Requete simple sur deux tables simultanées
    SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder FROM MySite_pictures a,MySite_albums b WHERE (a.idalbum=55 AND b.id=55) LIMIT 0,9
    Durée: 11.16851 s, Vitesse: 448 requetes par seconde
    Requete simple sur deux tables simultanées, cache active
    SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder FROM MySite_pictures a,MySite_albums b WHERE (a.idalbum=55 AND b.id=55) LIMIT 0,9
    Durée: 1.48137 s, Vitesse: 3375 requetes par seconde
    Requete AVEC JOIN
    SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder FROM MySite_pictures a, MySite_albums b JOIN MySite_albums ON a.idalbum=b.id WHERE a.idalbum=55 LIMIT 0,9
    Durée: 13.16669 s, Vitesse: 380 requetes par seconde
    Requete AVEC JOIN et cache
    SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder FROM MySite_pictures a, MySite_albums b JOIN MySite_albums ON a.idalbum=b.id WHERE a.idalbum=55 LIMIT 0,9
    Durée: 1.30094 s, Vitesse: 3843 requetes par seconde
    La différence est phénoménale dans mon cas, ca va entre 8 et 9 fois plus vite

    Voici le code que j'ai utilisé, pour ceux que ca interesse. Il n'a subit aucune optimisation particulière; il devrait donc être encore possible d'améliorer le résultat.

    Code de Test
    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
    	echo '<h2>Requete simple sur deux tables simultanées</h2>';
    	$SQL = "SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder 
    			FROM $Table_Pictures a,$Table_Albums b WHERE (a.idalbum=$Album_ID AND b.id=$Album_ID) LIMIT $FirstPic,$galPicturesPerPage";
    	echo $SQL.'<br>';
    	start();
    	for ($i=0; $i<5000; $i++){
    	$myPictures = $myDB->Query($SQL);
    	};
    	stop();
    	echo resultat(5000, 'requetes');
     
    	echo '<h2>Requete simple sur deux tables simultanées, cache active</h2>';
    	$SQL = "SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder 
    			FROM $Table_Pictures a,$Table_Albums b WHERE (a.idalbum=$Album_ID AND b.id=$Album_ID) LIMIT $FirstPic,$galPicturesPerPage";
    	echo $SQL.'<br>';
    	start();
    	for ($i=0; $i<5000; $i++){
    	$myPictures = $myDB->Query($SQL, true);
    	};
    	stop();
    	echo resultat(5000, 'requetes');
    (Il y a la même chose avec la deuxieme requête)

    La suite, le code de ma classe qui effectue la requete
    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
    	 /**********************************************************************
    	 *	Generic SQL query.
    	 ***********************************************************************
    	 *	@param $query  	
    	 *	@retrun : 
    	 **********************************************************************/				
    		function Query($query, $Cache = false){
    			//Create the name of the file wich could contain the values
    			$filename = $_SERVER['DOCUMENT_ROOT'].'/cache/'.md5($query).'.txt';
    			if (!(strpos($query, 'SELECT') === false) && ($Cache == true) && file_exists($filename) && is_readable($filename)){
    				$result = array();
    				$result = $this->LoadArrayFromFile($result, $filename);
    				return $result;
    			} else {		
    				//If there's no existing connection to the server, 
    				//let's try to create one.
    				if (!$this->dbConnected){ $this->Connect();};
    				//If there's a connection to the server and if we can acces the 
    				//database we can execute our query
    				if ($this->dbConnected && $this->OpenDataBase()){
    					//Construct the query
    					$myQuery = $query;
    					$this->LastQuery  = $myQuery;				
    					if ($res = mysql_query($myQuery)){
    						$result = array();
    						$i = 0;
    						while ($data = mysql_fetch_row($res)){
    							$j = 0;
    							foreach ($data as $item){
    								$result[$i][mysql_field_name($res,$j)] =  $data[$j];
    								$j++;
    							}
    							$i++;
    						};			
    						if (!(strpos($query, 'SELECT') === false) && ($Cache = true)){
    							//Store the result in the file for the next time 
    							$this->SaveArrayToFile($result, $filename);
    						};		
    						return $result;
    					} else {
    						$this->errorMessage = '<i>'.$myQuery.'</i><br/>'.mysql_error();
    						$this->errorNumber = mysql_errno();
    						if ($this->Debug){	$this->GetLastError();};							
    					};
    				};
    			};
    		}
    ET enfin, les deux procedures que j'ai écrite pour stocker mes array dans des fichiers et les recharger par après
    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
    	 /**********************************************************************
    	 *	Save an array in a text file. An implicit conversion from each item
    	 *	in the array to string must be possible otherwise it shouldn't work.
    	 *	The array may contain arrays but those cannot.
    	 ***********************************************************************
    	 *	@param &$array : pointer to the array to store
    	 *	@param $filename : name of the file where the value must be saved	
    	 *	@retrun : /
    	 **********************************************************************/			
    		function SaveArrayToFile(&$array, $filename){
    			$Header = implode(', ',array_keys($array[0]))."\r\n";
    			$Content = '';
    			foreach ($array as $item){
    				//Pour chaque photo
    				$Content .= implode(', ',$item)."\r\n";				
    			};
    			$handle = fopen($filename, "w+");
    			fwrite($handle, $Header.$Content);
    			fclose($handle);	
    		}
     
    	 /**********************************************************************
    	 *	Load an array form a text file. An implicit conversion from string 
    	 *	to the original type must be possible otherwise it shouldn't work.
    	 ***********************************************************************
    	 *	@param $filename : name of the file where the value has been saved	
    	 *	@retrun : loaded array
    	 **********************************************************************/					
    		function LoadArrayFromFile($filename){
    			$handle = fopen($filename, "r");
    			$Text = fread($handle, filesize($filename));
    			fclose($handle);	
    			$Content = explode("\r\n", $Text);
    			//Recuperer les index des champs
    			$i = 0;
    			foreach(explode(", ", $Content[0]) as $item){
    				$Keys[$i] = $item;
    				$i++;
    			};
    			$Text_Count = count($Text);
    			for($i=1; $i<$Text_Count; $i++){
    				$j = 0;
    				foreach(explode(", ", $Content[$i]) as $item){
    					$array[$i-1][$Keys[$j]] = $item;
    					$j++;
    				};
    			};
    		}			
     
    	};
    En modifiant ces deux dernières fonctions pour sérializer/desérialiser le tableau, on perd un peu en performance mais on gagne en souplesse
    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
     
    	 /**********************************************************************
    	 *	Save an array in a text file. 
    	 ***********************************************************************
    	 *	@param &$array : pointer to the array to store
    	 *	@param $filename : name of the file where the value must be saved	
    	 *	@retrun : /
    	 **********************************************************************/			
    		function SaveArrayToFile(&$array, $filename){
    			$handle = fopen($filename, "w+");
    			fwrite($handle, serialize($array));	//fwrite($handle, $Header.$Content);
    			fclose($handle);	
    		}
     
    	 /**********************************************************************
    	 *	Load an array form a text file. 
    	 ***********************************************************************
    	 *	@param $filename : name of the file where the value has been saved	
    	 *	@retrun : loadded array
    	 **********************************************************************/					
    		function LoadArrayFromFile($filename){
    			$handle = fopen($filename, "r");
    			$Text = fread($handle, filesize($filename));
    			fclose($handle);	
    			$array = unserialize($Text);
    		}			
    	};
    Requete simple sur deux tables simultanées
    SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder FROM MySite_pictures a,MySite_albums b WHERE (a.idalbum=55 AND b.id=55) LIMIT 0,9
    Durée: 11.7862 s, Vitesse: 424 requetes par seconde
    Requete simple sur deux tables simultanées, cache active
    SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder FROM MySite_pictures a,MySite_albums b WHERE (a.idalbum=55 AND b.id=55) LIMIT 0,9
    Durée: 1.48182 s, Vitesse: 3374 requetes par seconde
    Requete AVEC JOIN
    SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder FROM MySite_pictures a, MySite_albums b JOIN MySite_albums ON a.idalbum=b.id WHERE a.idalbum=55 LIMIT 0,9
    Durée: 13.24316 s, Vitesse: 378 requetes par seconde
    Requete AVEC JOIN et cache
    SELECT a.id, a.filename, a.title, a.author, a.description, a.added, b.folder FROM MySite_pictures a, MySite_albums b JOIN MySite_albums ON a.idalbum=b.id WHERE a.idalbum=55 LIMIT 0,9
    Durée: 1.51247 s, Vitesse: 3306 requetes par seconde

  4. #224
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 68
    Points : 72
    Points
    72
    Par défaut
    Citation Envoyé par iubito
    Si on écrit en ligne y'a plus aucun intérêt à faire des concaténation, autant faire directement echo '<table><tr>...';

    Parfois on présente sur plusieurs lignes pour s'y retrouver dans le code PHP.
    Salut

    vous êtes au courant que :

    echo '<table>
    <tr>
    <td>Contenu du td</td>
    </tr>
    </table>';

    marche aussi trés bien et à mon avis est bien plus lisible que votre concaténation de chaîne innutile à moins qu'une variable n'intervienne dans le chmilblique ...

  5. #225
    Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Dans une fonction, est-ce qu'on est obligé de faire un unset à la fin de la fonction de toutes les valeurs créées dans la fonction si on veut que çà soit optimiser à mort OU est-ce que ces valeurs sont d'elles mêmes unset(er) dès le moment où l'appel à la fonction a été fait !

    Autre question, personnellement je fais toutes mes requetes et la construction en html de la mise en forme de ces données en haut de page. JE rassemble tout dans une variable $toto. Je ferme ensuite ma connexion MySQL. Et je fais un echo $toto dans le body de la page qui est déjà préformatée avec un template dreamweaver. Est-ce c'est bon comme çà ?

    Ensuite, après le </html> je fais un unset des variables que j'ai utilisé. Est-ce utile en toute fin de page ?

    Merci encore pour vos précieux conseils

  6. #226
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Salut

    Non, appeler unset() est inutile en fin de fonction et en fin de script : PHP s'en charge.
    Parfois (souvent), il ne faut pas penser à l'optimisation d'un script (réduire le temps d'exécution) mais à l'organisation du code (permettre une relecture facile).

  7. #227
    Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Yogui
    Salut

    Non, appeler unset() est inutile en fin de fonction et en fin de script : PHP s'en charge.
    Parfois (souvent), il ne faut pas penser à l'optimisation d'un script (réduire le temps d'exécution) mais à l'organisation du code (permettre une relecture facile).
    Donc on a donc tout intérêt à mettre nos traitements dans des fonctions ?

    Quant à la relecture facile, tu entends pour le développeur ou simplement pour PHP ?

    Autre question bête :
    si j'ai une structure de ce type:
    requete1
    traitement1
    requete2
    traitement2
    requete3
    traitement3

    ai-je intérêt à fermer mysql après CHAQUE requête ? ou simplement de le faire à la fin de mon script !?!

  8. #228
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    J'entends pour le développeur car PHP ne "lit" pas, il "parse".
    Tu as intérêt à mettre tes traitements répétés dans des fonctions, pas les autres.

  9. #229
    Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Yogui
    J'entends pour le développeur car PHP ne "lit" pas, il "parse".
    Tu as intérêt à mettre tes traitements répétés dans des fonctions, pas les autres.
    Ca je l'ai fait depuis bien longtemps évidemment !
    Je parlais simplement pour optimiser des pages très regardées que j'ai besoin d'optimiser à mort (bcp de hits) notamment pour libérer de la mémoire.

    Aurais-tu une idée par rapport à l'exemple que j'ai donné sur mon post précédent par rapport aux fermetures mysql_close ?

  10. #230
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Utiliser les fonctions mysql_ n'est pas une optimisation. Il y a au moins deux méthodes plus efficaces : les extensions mysqli et pdo/pdo_mysql.

    Exemple avec PDO :
    http://g-rossolini.developpez.com/tu...ite-dynamique/

    Là, tu gagneras en performances. Il me semble que quelqu'un nous a promis un comparatif là-dessus mais peut-être me trompé-je.

    [Edit] Beaucoup de hits simultanés ?
    Est-ce que ton serveur a vraiment besoin d'être optimisé à fond ?
    Si oui, peut-être serait-il intéressant de penser à Zend Optimizer.

  11. #231
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 882
    Points : 691
    Points
    691
    Par défaut
    Utiliser les fonctions mysql_ n'est pas une optimisation. Il y a au moins deux méthodes plus efficaces : les extensions mysqli et pdo/pdo_mysql.

    Exemple avec PDO :
    http://g-rossolini.developpez.com/tu...ite-dynamique/

    Là, tu gagneras en performances
    c'est surtout qu'a terme les extention mysql,sybase,oci_8 ne seront plus misent a jour, au profit de PDO
    pour ce qui est des perfs pdo est plus rapide si on a un grand nombre de requete (preparées)

  12. #232
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    Citation Envoyé par stephane eyskens
    Je rajoute ceci:

    - évitez les "select *" lorsque vous ne devez ramener qu'une ou deux colonnes de la table.

    - Mettez des index sur les colonnes qui sont souvet dans les clauses "where", bon, faut pas non plus mettre des index à tout va car pour chaque insertion, l'index doit être mis à jour, d'où perte de performance. Il faut uniquement mettre des index sur des grosses tables et qui sont requêtées à 85% VS mise à jour.

    - évitez les variables intermédiaires inutiles
    Tiens justement !
    J'ai une table historique où j'effectue pour chaque page les trois requêtes suivantes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $insert="INSERT INTO `historique` 
    (`idMembre`,`url`,`dateLecture`,`dateNombre`,`numero`,`titre`,`couleur`)
    VALUES 
    ('$numeroConnexion','$retour','$dateLecture','$dateNombre','1','$titreHistorique','$couleur' )";
    mysql_query($insert);
     
     
     $update = "UPDATE historique SET numero=numero+1 WHERE idmembre= '".$numeroConnexion."' ";
     mysql_query($update);
     
     
    $update="DELETE FROM historique WHERE idMembre = '".$numeroConnexion."' AND numero > 100 ";
    mysql_query($update);
    Je n'affiche en revanche le contenu de cette table que sur une seule page dans le tableau de bord.
    J'ai des index sur trois champs de la table.

    Puisque tu dis qu'il y a perte de performance à chaque insert car l'index doit être mis à jour (pourquoi au fait?), alors est-il judicieux dans mon cas d'utiliser les index ?
    C'est pas parce que j'ai tort que vous avez raison.

  13. #233
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Salut

    Si je ne m'abuse, un index est utile principalement si l'on effectue de nombreuses recherches sur la table en question (par rapport aux insertions / modifications : cf. le message de Stéphane Eyskens). Dans le cas d'un historique, je doute que ce soit le cas...

    Si l'index est mis à jour, c'est bien sûr parce qu'il recense tous les enregistrements de chaque champ mis à l'index. Si un tuple est ajouté, il faut mettre à jour l'index.

    Tout était déjà dit, je ne sais pas si je suis + clair.

  14. #234
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    Donc à te lire, je vire les index de ma table historique. Vu qu'elle enregistre 100 pages vues par membre, ça peut très vite faire une table très importante.
    Donc qu'est ce qui va être le plus long ?
    Ne pas mettre à jour les index mais aller chercher dans la table tous les enregistrement pour un membre ou bien mettre à jour les index et aller chercher avec un index tous les enregistrements pour un membre.
    Sachant qu'en effet l'index doit être mis à jours à toutes les pages alors que l'historique n'est appelé qu'occasionnellement.
    C'est pas parce que j'ai tort que vous avez raison.

  15. #235
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Je vais me contenter de citer ce qui est dit juste au-dessus :
    Il faut uniquement mettre des index sur des grosses tables et qui sont requêtées à 85% VS mise à jour.

  16. #236
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 221
    Points : 472
    Points
    472
    Par défaut
    ok, cela étant j'ai du mal avec le jargon informatique :
    requêtées à 85% VS mise à jour
    C'est pas parce que j'ai tort que vous avez raison.

  17. #237
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Points : 29 985
    Points
    29 985
    Par défaut
    Cela signifie que les index ne sont utiles que si la proportion "requêtes de sélection" par rapport aux "requêtes d'insertion et de mise à jour" est de 85% par rapport à 15%.

    Il faut donc que tu cherches davantage que tu ne modifies la table. Ce n'est pas ton cas.

  18. #238
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Est-ce qu'on peut optimiser ce sujet ?
    Il est trop lourd à charger dans ma RAM grise.
    Most Valued Pas mvp

  19. #239
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    842
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 842
    Points : 696
    Points
    696
    Par défaut
    J'ai un résumé très simple : "Pour optimiser, il faut d'abord chercher ce qui est lent dans un programme, identifier les goulots d'étranglement". Ce résumé rends miraculeusement 90% de ce topic d'intérêt très faible : on connaît des solutions meilleures que d'autres mais dont l'application fait perdre en lisibilité contre des performances ne dépassant rarement les 1% d'amélioration. Parmi les conseils vraiment utiles, on peut citer Yogui en dernière page :

    Parfois (souvent), il ne faut pas penser à l'optimisation d'un script (réduire le temps d'exécution) mais à l'organisation du code (permettre une relecture facile).
    Et une URL :

    http://phplens.com/lens/php-book/opt...ugging-php.php

    ______
    Fin du résumé : D (à compléter évidement, ce s'rait un travail intéressant, mais très long)

    Il y avait des interventions intéressantes, mais c'est vrai que tout relire... Tous ce qui concerne l'optimisation des requêtes sur une base de donnée est quasiment utile, mais il faudrait certainement se référer au forum correspondant à la BDD utilisée. Il y en a beaucoup à prendre avec des pincettes. Genre, les calculs de temps d'execution en oubliant le temps de parsing. Et certaines solutions désignées comme "mauvaises" sont plus rapides à parser que les "bonnes" solutions. Ce qui revient à dire que le gain se fait uniquement dans des conditions de répétions, ou quand un cache d'opcode est activé. (Certains utilisent les optimisations, voir les conseillent dans leur signature, dans des cas qui sont hors de ces conditions) Cet exemple illustre bien la complexité de l'optimisation, quelque soit le langage d'ailleurs, et que l'on perd souvent beaucoup trop de temps à essayer d'optimiser pour des résultats ridicules voir insignifiants. (Et comme le dit implicitement Yogui à détruire la lisibilité du code) Gagner des microsecondes sur des scripts qui s'executent en des temps de l'ordre de la centaine de milliseconde ce n'est pas intéressant.


    Il y a des études d'optimisation de script qui peuvent être efficaces avec les bons outils. On peut programmer ces outils soit même, en php : l'astuce est donnée dans une page assez inconnue du manuel php :

    http://www.php.net/manual/fr/control...es.declare.php

    Avec une poignée de lignes, on peut calculer le temps d'execution d'un script ligne par ligne : on peut mesurer avec une marge d'erreur raisonable le temps que la machine passe sur chaque ligne, ce qui permet d'identifier au premier coup d'oeil ce qui prends du temps dans un code php, quelles fonctions, quelles lignes, en rapport avec le temps total d'exécution, y compris le temps passé dans un include pour récupérer le temps de parsing. A partir de là, on peut identifier les segments de code lents et seulement alors tenter de les optimiser.

  20. #240
    Membre éprouvé
    Inscrit en
    Juillet 2004
    Messages
    1 027
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 027
    Points : 1 164
    Points
    1 164
    Par défaut
    En termes plus pratiques un truc qui n'à pas été que peu abordé c'est la mise en cache des objets durant l'execution, c'est plutot pour php5.
    zaventem en à un peu parlé sur un cas extrèmement particulier.

    Bref, sa arrive souvent qu'un objet soit construit plusieurs fois pour une même représentation en base.

    Un exemple simple serait le cas d'une liste de produit ave des marques.
    Chaque objet produit pourrait avoir en son sein une référence vers une marque.
    Hors il arrive souvent qu'une marque appartiennent à de multiples produits différent.
    Ce qui, si l'on y fait pas attention, instanciera 20 objet de la marque toto.

    en conséquence on obtient :
    - Une rupture entre l'unicité de la marque en base, et l'unicité de la marque lors de sa transofmation en objet.
    - Alourdit betement l'application qui execute N requetes identique pour le même objet.

    Pour éviter ces pertes idiotes une bonne solution est de créer une petite classe de cache... et d'instancier ces objets au travers de méthodes statique. A bas le new Produit( $id );

    En code sa donne :
    Code méthode gourmande : 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
     
    class produit
    {
    	public $nom;
    	public $marque;
     
    	public function __construct( $id )
    	{
    		$sql = "SELECT * FROM ...";
    		$query ....
    		$res....
     
    		$this->nom = $res["nom"];
    		$this->marque = new Marque( $res["idmarque"]);
    	}
    }
     
    class Marque
    {
    	public $id;
    	public $nom;
     
     
     
    	public function __construct( $id )
    	{
    		$sql = "SELECT * FROM ...";
    		$query ....
    		$res....
     
    		$this->id = $res["id"];
    		$this->nom = $res["nom"];
    	}
    }

    Ou bien :

    Code méthode plus légére : 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
     
    class produit
    {
     
    	public $nom;
    	public $marque;
     
    	public function __construct( $id )
    	{		
    		$this->nom = NULL;
    		$this->marque = NULL;
    	}
     
    	public static function lire( $id )
    	{
    		$objet = Cache::Get( __CLASS__."lire".$id );
    		if( $objet != NULL )
    			return $objet;
     
    		$objet = new Produit();
     
    		$sql = "SELECT * FROM ...";
    		$query ....
    		$res....
     
    		$objet->nom = $res["nom"];
    		$objet->marque = Marque::lire( $res["idmarque"]);
     
    		 Cache::Put( $objet , __CLASS__."lire".$id );
     
    		return $objet;
    	}
    }
    class Marque
    {
     
    	public $id;
    	public $nom;
     
    	public function __construct( $id )
    	{		
    		$this->id = NULL;
    		$this->nom = NULL;
    	}
     
    	public static function lire( $id )
    	{
    		$objet = Cache::Get( __CLASS__."lire".$id );
    		if( $objet != NULL )
    			return $objet;
     
    		$objet = new Marque();
     
    		$sql = "SELECT * FROM ...";
    		$query ....
    		$res....
     
    		$objet->id = $res["id "];
    		$objet->nom = $res["nom"];
     
    		 Cache::Put( $objet , __CLASS__."lire".$id );
     
    		return $objet;
    	}
    }

    Et le petit bout de code qui va bien pour sauvegarder/lire des objets en cache :
    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
     
    //////////////////////////////////////////////////////////
    ///	\class Cache
    ///	Classe qui permet de mettre en mémoire des objets, puis de les récupérer
    //////////////////////////////////////////////////////////
    class Cache
    {
     
    	//////////////////////////////////////////////////////////
    	//	propriétés
    	//////////////////////////////////////////////////////////
    	private static $Cache = array();
     
    	//////////////////////////////////////////////////////////
    	///	constructeur
    	//////////////////////////////////////////////////////////
    	private function __construct()
    	{
    	}
     
    	//////////////////////////////////////////////////////////
    	///	Mets en un objet en cache
    	///	l'uoid (Unique Object ID) est un identifiant unique
    	//////////////////////////////////////////////////////////
    	public static function Put( $Object , $uoid )
    	{
    		if($Object == NULL)
    			return false;
    		if( $uoid == NULL)
    			return false;
     
    		self::$Cache[$uoid] = $Object;
     
    		return true;
    	}
     
    	//////////////////////////////////////////////////////////
    	///	Recherche un objet en cache
    	///	l'uoid (Unique Object ID) est un identifiant unique
    	//////////////////////////////////////////////////////////
    	public static function Get( $uoid )
    	{
    		if( isset( self::$Cache[$uoid] ) )
    			return self::$Cache[$uoid];
    		return NULL;
    	}
     
    	//////////////////////////////////////////////////////////
    	///	destructeur
    	//////////////////////////////////////////////////////////
    	public function __destruct()
    	{
    	}
    }
    Je me suis permit de poster cela car j'ai vu assez souvent sur le forum des forumeurs qui faisait cela : new Produit( $id ); ce qui me laisse pensé que ce que je viens d'exposer pourrait les aider à ne plus executer de requetes inutiles.

    voilou,

    bbye

Discussions similaires

  1. [Débutant] Accélérer et optimiser ses scripts PHP
    Par Metallic-84s dans le forum Langage
    Réponses: 6
    Dernier message: 24/03/2006, 12h37
  2. [MySQL] [SGBD] Script PHP/MYSQL d'access FTP
    Par ChRom dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 09/01/2006, 01h52
  3. Réponses: 9
    Dernier message: 05/01/2006, 12h24
  4. Recherche Login Script PHP & MySQL
    Par whbh dans le forum SQL Procédural
    Réponses: 9
    Dernier message: 01/12/2005, 16h45
  5. [MySQL] [Script]Optimisation de scripts Php/MySQL (2)
    Par copy dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 27/08/2004, 08h33

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