Augmenter les perfs de votre site web

WRInaute impliqué
Voici un post destiné à orienter les webmestres peu portés sur l'admin à améliorer les performances de leur site web.

Etant donné que je bosse sur un dédié avec Apache, PHP et MySQL, une partie de ces optimisations ne concernent que les personnes dans le même cas. C'est quand même très très courant ;-)

On est dans la partie administration, pas développement, j'omettrais donc volontairement ce qui concerne l'algorithmie, l'utilisation des CSS, la compression des images etc.

Base de données

Types des champs
Choisissez toujours le type le plus petit possible pour stocker vos données

Utilisation des indexs
N'oubliez pas de placer des indexs sur vos champs sur lesquels vous faites vos SELECT. C'est très simple à effectuer (vous pouvez le faire via PHPMyAdmin) et ça accélère vraiment BEAUCOUP les recherches en base.

MySQL 3.23
... est vraiment obsolète et surtout, n'inclus pas de cache. Passez aux versions supérieures pour bénéficier d'un système de cache, toujours appréciable.
Le meilleur mode est le mode manuel en précisant dans les requêtes si elles doivent être mises en cache ou non. Ca peut être un peu longuet, si ça vous parait être trop long, laissez-le en automatique.

Tables HEAP ou MEMORY
Ce sont des tables dont le contenu est "volatile". En cas de reboot, tous ses enregistrements seront perdus.
En revanche, ce type de table est très rapide puisque les données sont stockées en mémoire. Et puisqu'elles sont stockées en mémoire, il faut éviter d'utiliser ce type pour les grandes tables, à moins d'avoir beaucoup de RAM


Optimisation PHP

Cache d'opcode
Un cache d'opcode évite que PHP parse votre code à chaque appel de la page. De plus, le code compilé reste en RAM ce qui accélère encore grandement l'éxécution.
Le taux de réussite de ce genre de cache est très élevé (99%, par là), on voit donc tout son intérêt.
Je vous conseille APC, qui fait partie de PECL : http://pecl.php.net/package/APC

Cache d'objets
Vous pouvez utiliser un cache d'objets afin d'optimiser la consommation mémoire et éviter des requêtes SQL. Ce type d'optimisation est assez complexe, je vous laisse creuser par vous-même : http://www.danga.com/memcached/


Diminuez la consommation de bande passante

Utilisez la compression à la volée du code HTML. Cela consomme un peu plus de CPU mais cela a un impact direct sur la perception du temps de réponse des visiteurs.
Vous pouvez activer cette fonctionnalité au niveau du serveur Apache grace à mod_deflate (http://httpd.apache.org/docs/2.0/mod/mod_deflate.html), ou en activant la compression coté PHP (output_handler =ob_gzhandler dans PHP.ini)


Config d'Apache
Si comme moi vous n'en voyez pas l'intérêt, je vous conseille de ne pas logger tous les appels serveurs. Personnelement, le ne logge pas les appels aux images et feuilles de styles, ça évite d'avoir des fichiers énormes et limite les accès disques.

Evitez également l'activation des htaccess placés dans les répertoires et placez tout dans le fichier de conf de votre site, afin d'éviter beaucoup d'accès disque inutiles.


Cache de pages
Sans doute le plus radicale, il s'agit de sauvegarder les pages générées en HTML et de ne pas recalculer toute la page. Il faut savoir un minimum ce que l'on fait pour ne pas saturer le disque, et bien comprendre le processus d'élaboration des pages pour, par exemple, ne pas afficher une page périmée alors que son contenu a changé. Il est aussi possible de définir une durée de vie de la page, ce qui peut être suffisant si le contenu ne vient pas des visiteurs. Dans le cas contraire (commentaires...), vos visiteurs risquent de ne pas comprendre et de poster plusieurs fois.
Je vous conseille Cache_Lite, qui fait aussi partie de PEAR.
Un tuto ici : http://developpeur.journaldunet.com/tut ... he1a.shtml

Voilà, c'est tout pour aujourd'hui. Suivant la manière dont est organisé et codé votre site, et les optimisations que vous avez déjà mis en place, les gains varieront. Mais si pour le moment, vous ne vous êtes jamais penché sur l'optimisation, vous pourrez être surpris par les résultats...
 
WRInaute occasionnel
yanhl a dit:
Utilisation des indexs
N'oubliez pas de placer des indexs sur vos champs sur lesquels vous faites vos SELECT. C'est très simple à effectuer (vous pouvez le faire via PHPMyAdmin) et ça accélère vraiment BEAUCOUP les recherches en base.

Les indexes sont à placer sur les champs sur lesquels on utilise des clauses Where dans les requêtes. Les champs que l'on sélectionne dans ces requêtes n'ont pas besoin d'être indexés.
Ex : SELECT a,b,c,d FROM table WHERE x=3
Index à placer sur champ "x" uniquement, le reste ne sert à rien.
 
WRInaute impliqué
oui, merci de préciser. en fait, c'est tout ce qui sert à restreindre ou classer la sélection et à faire les jointures.
Si vous faites un SELECT * FROM articles WHERE parution<NOW() ORDER BY auteur_id

Il faut indexer les champs parution et auteur_id
 
WRInaute discret
Merci pour ce post, je ne possède pas de serveur dédié, mais j'ai tout de même repéré deux ou trois astuces à garder.

Merci à toi pour ce résumé.
 
WRInaute passionné
yanhl a dit:
oui, merci de préciser. en fait, c'est tout ce qui sert à restreindre ou classer la sélection et à faire les jointures.
Si vous faites un SELECT * FROM articles WHERE parution<NOW() ORDER BY auteur_id

Il faut indexer les champs parution et auteur_id

Sur les index, je ne suis pas aussi catégorique que toi.
- Il faut toujours indéxer les clés : clés primaires, clés étrangères

Pour les autres colonnes, je n'indexe pas systématiquement. J'indexe les colonnes qui sont souvent utilisés dans les clauses where ( ou éventuellement dans les jointures ). La notion de souvent étant très arbitraires.

Ensuite il faut être prudent. Il ne sert à rien d'indéxer, si on utilise pas les index dans les requêtes.

Un exemple concret :
ng int,
nd int,
KEY idx_ng (ng)

Deux champs de type int et un index sur le champ ng.
Si tu fait cette requête :
Code:
WHERE nd - ng = 1
ton index sur ng ne sera pas utilisé.

Il faut réécrire ta requête pour bénéficier de l'index sur ng.
Code:
WHERE  ng = nd - 1

Ce post est une excellente initiative.
 
WRInaute impliqué
A noter pour les select il y a la commande explain en faisant preceder le select avec explain vous obtiendrez des infos sur comment est traitée la requète.

Pour en revenir au index, attention souvent lors de reboot sauvage ce sont eux qui trinquent et ainsi la base peu devenir bancale. D'ailleur je conseille de reconstruire les index chaque fois qu'il y a eu un problème serveur

Toujour d'aussi bon Post Yanhl bravo

A+
 
WRInaute discret
En ce qui concerne MySql : le cache oui, mais les requêtes qui consomment : non ! Après avoir indexé correctement, il faut vérifier quelles sont les slow queries et les queries without index et y rémedier !

Je rajouterai aussi : utiliser asp.net pour pouvoir bien gérer le cache de pages, de composants et de données, et avoir du code compilé.

A oui j'oubliai il manque aussi le cache navigateur : 1 jours pour les images/css/js.

Avec tout ça ça carbure ! :)
 
WRInaute impliqué
Je rajouterai aussi : utiliser asp.net pour pouvoir bien gérer le cache de pages, de composants et de données, et avoir du code compilé.
Euuuh... si on a un site en ASP, bien sûr ;-)

A oui j'oubliai il manque aussi le cache navigateur : 1 jours pour les images/css/js.
Comment tu fais ça ?
 
WRInaute accro
>> Comment tu fais ça ?

ben tu fais pas, c'est l'internaute qui fait. ca ne rentre pas dans ce topic
 
WRInaute impliqué
ben tu fais pas, c'est l'internaute qui fait. ca ne rentre pas dans ce topic
Il semblerait bien que si : http://httpd.apache.org/docs/1.3/mod/mod_expires.html

Edit : par contre je ne vois aucune différence, les tags HTML d'image continuent d'envoyer des requêtes et le serveur de répondre par des 304. problème de conf ? Le principe est-il bien de faire en sorte que les navigateurs ne produisent même plus de requêtes pour les images qui ont été envoyées avec un header d'expiration à 1 jour ?
 
WRInaute discret
> yanhl

Oui c'est bien ça (pour apache).

Ca change la vie ! :D
Ceux qui peuvent le faire, faites le !

Un logiciel excellent (et gratuit) à télécharger est "Fiddler"(http://www.fiddlertool.com/), il permet de voir ce qui se passe au niveau HTTP (les fichiers qui sont mis en cache ont la couleur de texte en violet).

Techniquement Fiddler émule un serveur Proxy, pas bête :D
 
WRInaute impliqué
yes, fiddler c'est bien (à utiliser avec IE, il ne capte pas les requêtes de FF), pour FF y'a LiveHTTPHeader

Mais quand je l'active et que je vais sur ton site, je vois toujours des requêtes pour les images et des réponses 304, bref rien de différent d'une install apache de base :?:

Je vois aussi un max de requêtes Ajax, je ne sais pas ce que tu actualises comme ça mais en tout cas ça y va ! ;-)
 
WRInaute discret
Fiddler marche aussi avec FireFox il faut juste paramètrer l'adresse du serveur proxy (en l'occurence : localhost, port 8888).

Regarde le Header de retour et la partie "Cache", c'est ce qui est intéressant.
Si tu raffiche la page d'accueil (sans actualiser), tu verras que ça ne charges plus grand chose.
Pour ajax c'est une autre histoire qui n'a pas sa place dans ce thread :p, mais sache que le traffic n'est pas du tout important dans mon cas
 
WRInaute accro
.
Je me permets de rajouter un point :

vous disiez qu'il fallait ajouter un index aux champs qui sont souvent utilisés avec une condition where, ou autre..dans la plupart des cas ce n'est pas faut, mais il faut savoir que dans le cas ou il y a plus d'accès en écriture les index ralentissent énormément. Ces cas sont plus rare mais peuvent éxister.
 
WRInaute impliqué
Cas rare effectivement, mais qui peut arriver avec certains logiciels de statistiques. A ce propos, réfléchissez avant d'installer un tel script qui fait au minimum un accès base ou disque, au pire un appel de page + une connexion à la base + plusieurs requêtes pour chaque page consultée par vos visiteurs.

Avis personnel : il vaut mieux utiliser un service externe plus qui offre souvent plus d'infos (Google analytics vs phpMyVisites, au hasard) qui ne vous prendra aucune ressource, ou un analyseur de fichiers logs si les infos dispos par Javascript uniquement ne vous intéressent pas (résolution, nb de couleurs, flash installé...).
 
WRInaute discret
Je ne suis pas entièrement d'accord. Les outils de stats sont très bien pour établir une moyenne de ce qui se passe sur son site.

Si on veut en savoir plus sur un point spécial, il vaut mieux écrire ses propres scripts.

Je m'en sers pour les HTTP_REFERER qui sont largement filtrés dans les outils de statistiques.
 
WRInaute passionné
En terme de perf, le SGBD est souvent un goulot d'étranglement. Il n'est pas toujours possible d'intervenir directement sur la configuration du SGBD, sauf pour ceux qui ont leur propre serveur dédié.

1. Réfléchissez bien à votre modèle de donnée
Les erreurs de conception de votre modèle de donnée seront lourdes de conséquences en terme de performances plus tard.
Vous devrez faire des efforts d'optimisation considérables pour compenser les erreurs à ce niveau.

2. Ne mettez jamais de requête dans une boucle
Mettre une requête SQL dans une boucle est un bon moyen de mettre à genou votre serveur SQL.
Il existe certainement une meilleure solution réduisant la charge serveur.
Cette solution vous obligera certainement à ré-écrire votre requête.

3. N'hésitez pas à réfléchir et à tester vos requêtes avant de développer.
- Cela vous permettra de débusquer assez tôt des erreurs de conception
- Vous pourrez optimiser vos index ( explain en mysql )

C'est au niveau SQL que vous pouvez avoir des gains de performances important. Ces gains seront facile à obtenir si la conception initiale est bonne.
 
WRInaute impliqué
Je ne suis pas entièrement d'accord. Les outils de stats sont très bien pour établir une moyenne de ce qui se passe sur son site.

Si on veut en savoir plus sur un point spécial, il vaut mieux écrire ses propres scripts.

Je m'en sers pour les HTTP_REFERER qui sont largement filtrés dans les outils de statistiques.

A mon avis, ça ne rentre plus dans le cadre de l'optimisation des perfs, ce dont tu parles concerne le fonctionnel/marketing.

Si on garde une optique "optimisation pure", on évitera de faire les choses deux fois.
Puisqu'on est légalement obligés de conserver des logs, il vaut mieux se prendre un bon analyseur de logs brutes type Webtrends, ou bien dans ton cas faire des scripts pour parser les logs apache, les mettre en base de donnée et les analyser... mais offline.
 
WRInaute discret
yanhl a dit:
Utilisation des indexs
N'oubliez pas de placer des indexs sur vos champs sur lesquels vous faites vos SELECT. C'est très simple à effectuer (vous pouvez le faire via PHPMyAdmin) et ça accélère vraiment BEAUCOUP les recherches en base.

Concretement on fais comment dans phpmyadmin ?
Il faut le faire généralement sur le champ sur lequel on fait le WHERE ?
 
WRInaute passionné
yakipa a dit:
yanhl a dit:
Utilisation des indexs
N'oubliez pas de placer des indexs sur vos champs sur lesquels vous faites vos SELECT. C'est très simple à effectuer (vous pouvez le faire via PHPMyAdmin) et ça accélère vraiment BEAUCOUP les recherches en base.

Concretement on fais comment dans phpmyadmin ?
Il faut le faire généralement sur le champ sur lequel on fait le WHERE ?

Si mes souvenirs sont bons il te suffit de cocher le champ sur lequel tu veux créer un index.
 
WRInaute discret
Merci , visiblement tous mes ID (clé primaire) sont en index :)

par contre ca je comprend pas trop :
Config d'Apache
Si comme moi vous n'en voyez pas l'intérêt, je vous conseille de ne pas logger tous les appels serveurs. Personnelement, le ne logge pas les appels aux images et feuilles de styles, ça évite d'avoir des fichiers énormes et limite les accès disques.


C'est a dire ? en gros desactiver les logs ?
 
WRInaute impliqué
yakipa> exemple :

SetEnvIf Request_URI \.gif image-request
SetEnvIf Request_URI \.jpg image-request
SetEnvIf Request_URI \.png image-request
SetEnvIf Request_URI \.css image-request
SetEnvIf Request_URI \.js image-request
CustomLog /path_de_ton_log/access.log combined env=!image-request
 
WRInaute discret
yanhl a dit:
Config d'Apache
Evitez également l'activation des htaccess placés dans les répertoires et placez tout dans le fichier de conf de votre site, afin d'éviter beaucoup d'accès disque inutiles.

Ca c'est un truc que je ne connaissais pas, bon tuyau en effet, la conf et autre rewrite en tout genre sont alors chargé en mémoire une bonne fois pour toute au demarrage d'Apache.
...pas oublier de le redemarrer par contre si l'on fait une modif dans httpd.conf :p

Pour en revenir a MySQL et aux index en particulier, pour avoir longuement "étudié" le sujet...les index (entre autre) ont un impact non négligeable sur les perfs MySQL ... mais ça va aussi bien dans un sens que dans l'autre.
En clair il vaut mieux ne pas avoir d'index du tout que des index mal placés, sinon c'est pire que le mal.

EXPLAIN est indispensable, le plus dur est d'interpréter le résultat.

J'ai beaucoup appris grace a une personne (Daniel) webmaster d'un site malheureusement inaccessible depuis déjà qqs jours --> http://codenode.com/ ... je n'ai jamais trouvé d'équivalent, ce site était une véritable mine d'or. *

Au titre des autres améliorations (toutefois minimes // aux index) le type de champ est important et afin d'éviter le trasntypage, vérifier que les champs identiques (un ID par exemple) soit enregistré dans un champ identique.

* j'ai retrouvé (merci le cache de Google) trois articles interessants et qui m'ont été très utile.

Optimizing Slow Queries Case 1: Basic Indexes
Optimizing Slow Queries Case 2: Table Design and Index Details
Optimizing Slow Queries Case 3: ORDER BY With LIMIT and ANALYZE

De la bonne ET saine lecture :)
 
WRInaute impliqué
yanhl a dit:
Evitez également l'activation des htaccess placés dans les répertoires et placez tout dans le fichier de conf de votre site, afin d'éviter beaucoup d'accès disque inutiles.
Salut et merci beaucoup pour ces précieux conseils Yanhl.

Etant donné que mon site est hébergé en mutualisé, je n'ai pas d'autres choix pr configurer des régles de reécritures (par exemple) que de placer des fichiers .htaccess dans différents répertoires.
Sur ce point particulier, j'aimerais plus de précisions s'il te plaît :

- Dans quelle mesure est-ce pénalisant ? Les temps d'affichage sont allongés de 0.1, 0.5, 1 seconde... ?
- Toutes les pages de mon site (même celle qui ne sont pas "reécrites") sont-elles affectées par ce ralentissement ?
- Est-ce que seuls les premiers affichages d'un repertoire contenant un .htaccess sont ralentis ? Ensuite, les règles du .htacess de ce répertoire sont gardés en mémoire par le serveur un certain temps et il n'y a plus d'accés au disques ?
Si c'est le cas, est-ce que ça voudrait dire que le pis allé serait de centraliser toutes nos règles dans un fichier .htaccess unique placé à la racine du site ?

Par avance, merci à tous ceux qui pourraient m'éclairer :)
 
WRInaute impliqué
Je te recommande la doc d'Apache, page sur les htaccess, point "When (not) to use .htaccess files" ( http://httpd.apache.org/docs/trunk/howto/htaccess.html ) qui répond à toutes tes questions, excepté la perte de performance qui est difficilement quantifiable.
Ca dépend de beaucoup de choses : nombre de fichiers dans la page, profondeur dans l'arborescence, cache disque, etc etc.
Mais ça n'est pas de l'ordre de la seconde en tout cas, c'est quasi certain ;-)
 
WRInaute impliqué
Ah ! Merci bien pour ce lien, ça répond effectivement à mes questions (et ce, de façon compréhensible, ce qui n'est pas toujours le cas avec les docs techniques).
:wink:

A+
 
Discussions similaires
Haut