JeuWeb - Crée ton jeu par navigateur
Optimisation bis (axée requetes) - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Optimisation bis (axée requetes) (/showthread.php?tid=363)



Optimisation bis (axée requetes) - gtsoul - 26-10-2006

Ce sujet complète le sujet sur les principes d'optimisation.
car je trouve que maegia axe trop sa présentation sur le benchmark des fonctions.

Il y optimisation réelle et grattage de pouillièmes de secondes. La deuxième n'est pas inutile sur une appli mais uniquement quand la première a été faite sérieusement. On peut gagner plusieurs dixièmes sur une génération de html, sans essayer de gratter sur les fonctions qui vous font gagner 1 centième sur 10.000 itérations.

pour reprendre pascaltje,
mysql_fetch_array(), mysql_fetch_assoc(), mysql_fetch_row laquelle choisir ?
Déjà oublier mysql_fetch_array() qui indexe doublement ses champs et donc qui crée un index qui se trouve inutilisé. En plus plusieurs hébergeurs surchargent cette méthode pour la rendre inopérante.
Utiliser mysql_fetch_row pour récupérer un champ unique et mysql_fetch_assoc pour lever les ambiguités sur plusieurs champs

mais cela ne suffit pas.

La programmation orientée objet aide beaucoup le programmeur et le serveur et renforce la sécurité. Cela économise le programmeur car cela encapsule les traitements de manière logique. Ainsi un script de combat de 600 lignes se résume en 40-50 lignes.

Appeler une méthode au lieu de réaliser deux fois le même code, économise le clavier mais surtout centralise les erreurs. Si une erreur survient, c'est que la méthode est buggée, vous n'avez qu'elle à changer. A l'instar d'une programmation plus classique ou vous devez changer chaque occurence.

De plus, cela économise le serveur car les classes sont chargées en cache (comme les images), aussi la génération du code prend beaucoup moins de temps. Aussi, ne réinventez pas la roue; des classes ultrauberoptimisées et opensource sont disponibles sur le net et améliorent vos traitements courants de bas-niveau (comme mysqli, bibliothéque php-mysql improved).







Maintenant revenons sur les requetes car c'est peut-être l'un des points les plus optimisables. Pourquoi ? C'est un traitement ayant pour base des chaines de caractères (très consommatrices de mémoire) en relation avec un serveur distinct de celui où est traité votre code php (donc chaque accès coute en ressource).
Le principe n'est pas d'être radin sur les ressources mais de les utiliser au mieux.
Et puis aussi parce que c'est un sujet que personne n'a abordé ici !!

Optimisation de sa base :
Cela passe par la conception et le respect des règles d'optimisation. Si vous débutez et faites votre table à la volée, ce sera loin d'être le cas. Deux méthodes existent Merise et UML (personnellement, je préfère Merise pour construire ma bdd et UML pour mes classes).
Pour le schéma général de votre appli, je vous conseille vivement MVC (model-view-controller); mais il difficilement applicable en php (plus adapté pour du java/struts).
Bref, y'a pas de mystère; soit on se met à coder comme un bourrin et on ne dépassera jamais le stade du je-code-seul-au-fond-de-mon-garage-car-mes-programmes-sont-inmaintenables; soit on se paye un bouquin traitant du sujet du même nom et on le bosse! Y'a aussi les tutaux sur internet, mais bon, un bouquin c'est plus complet, c'est transportable, ca fait vivre les librairies et on y raconte moins de betises que sur les tutaux en ligne (que je n'utilise que pour compléter mes connaissances et non pour les acquérir).

Optimisation des requêtes :
Si vous savez optimiser votre base, vous saurez optimiser votre code sql. Mais vous ne saurez pas forcement optimiser la manière dont vous les effectuez (et là c'est du php).

Manière horrible : mysql_query("SELECT nom FROM t carte WHERE x =".$x." AND y=".$y." AND carte='".nom."' LIMIT 1");
si vous passez par un string $sql = "SELECT ... LIMIT 1";
si vous changez l'ordre des guillemets ou les enlevez c'est tout aussi horrible.
Car ce n'est que du sucre syntaxique et cela ne changera pas la manière dont le moteur interprétera votre code (et en plus avec les guillemets, on peut se paumer).

Pourquoi c'est si horrible ? Parce que !
Voici comment le moteur de php interpreterait
Code PHP :
<?php 
$sql
= "SELECT nom FROM t carte WHERE x =".$x." AND y=".$y." AND carte='".nom."' LIMIT 1";

1. $sql = 'SELECT nom FROM t carte WHERE x =';
2. $x = 44; //entier
3. $x = '44'; //string
4. $sql = 'SELECT nom FROM t carte WHERE x ='.'44';
5. $sql = 'SELECT nom FROM t carte WHERE x = 44'.' AND y=';
6. $y = 56; //entier
7. $y = '56'; //string
8. $sql = 'SELECT nom FROM t carte WHERE x = 44'.' AND y='.'56';
9. $sql = 'SELECT nom FROM t carte WHERE x = 44 AND y=56'.' AND carte=\'';
10. $nom='terres chaotiques';
11. $sql = 'SELECT nom FROM t carte WHERE x = 44 AND y=56 AND carte=\''.'terres chaotiques';
12. $sql = 'SELECT nom FROM t carte WHERE x = 44 AND y=56 AND carte=\'terres chaotiques'.'\' LIMIT 1';

Voilà, ces douze lignes équivalent le code qui se cache derrière celui de la première ligne; et prendront le même temps à la résolution. Si vous ne l'avez pas vu c'est que php est très puissant et réalise les casts et les concaténations sans que vous ne les voyez. Mais cela ne veut pas dire qu'il fournit moins d'efforts.
Comme on dit ce n'est pas en cassant le thermomètre qu'on n'a plus la fièvre.
Pour résumer, il nous a fallu pour effectuer cette simple ligne :
_ 2 castages
_ 6 concatenations

Nous allons essayer de réduire ce score par moitié; et par la même occasion gagner 50% de temps.
La solution :








Faire des requetes préparées.
Ceux qui codent d'autres languages objets "récents" connaissent peut être ce système.
Il consiste à définir un pattern que l'on remplira avec des variables. C'est certes plus lourd et plus contraignant, mais si vous vous débrouillez en poo, vous n'avez qu'à mettre le tout dans une classe.
Les avantages procurés :
_ l'utilisation de concaténations sauvages est limité
_ les requêtes sont réutilisables contrairement aux requêtes simples qui ne font que regénérer une nouvelle chaine (donc bonjour la charge si on repète une centaine de fois l'opération, ce qui peut être courant).
_ en sus, vous pouvez tracer/logger facilement vos erreurs. Ca évite les posts du genre "help pb sql" avec un "mysql_error() on line 67" pour seul indice.

Cette fonctionnalité est fournie par PDO depuis php 5.1 et mysql 4.1. Certes c'est récent mais si vous débutez autant prendre les bonnes habitudes; sinon vous n'avez qu'à convaincre votre hébergeur ou posséder un serveur dédié, na!

Comment cela fonctionnerait-il ?
Code PHP :
<?php 
1. $sql
= "SELECT nom FROM t carte WHERE x =? AND y=? AND carte=? LIMIT 1";
2. ? = 44;
3. ? = '44';
4. $sql = "SELECT nom FROM t carte WHERE x ='.'44'.' AND y=? AND carte=? LIMIT 1";
2. ? = 56;
3. ? = '56';
4. $sql = "SELECT nom FROM t carte WHERE x =44 AND y='.'56'.' AND carte=? LIMIT 1";
5. ? = 'terres chaotiques';
6. $sql = "SELECT nom FROM t carte WHERE x =44 AND y=56 AND carte=\''.'terres chaotiques'.'\' LIMIT 1";
Résultat :
_ 2 castages et 3 concaténations
_ plus la réutilisabilité, reprendre cette requête avec d'autres variables prendra moins de temps que précédemment (vous pouvez faire un test de charge).
=> Plus de 50% de gain !!


En gros ca va donner quoi ? (On veut le code !)
Ben comme d'hab le site du zéro : (je suis pas très pédagogique)
http://www.siteduzero.com/tuto-3-4404-1-mysql-requete-preparee.html

Quel est l'intérêt de vous saouler pour vous balancer finalement un simple lien ?
1. ce n'est pas moi qui ai inventé les prepared statement
2. il y aura toujours une personne pour en parler mieux que moi
3. Les tutaux en doublons ca sert à rien
4. je me contente de vous informer de l'existence d'un tel système
5. j'aime bien dissocier le fonctionnement du code, car c'est la chose la plus difficile à comprendre (le fonctionnement, pas le code c'est bateau)


RE: Optimisation bis (axée requetes) - orditeck - 26-10-2006

L'aide pour ce tutoriel ce trouve à cette adresse :
http://www.jeuweb.org/board/showthread.php?tid=551