Un temps de génération de 320 millisecondes s’affiche dans un en-tête Server-Timing, ou dans l’onglet réseau du navigateur. Cette valeur unique cache pourtant trois réalités bien distinctes, chacune répondant à une cause différente et appelant une correction différente. Confondre ces trois parts conduit souvent à optimiser la mauvaise chose.
Ce billet propose de décomposer ce temps total en trois composantes mesurables séparément : le temps passé à attendre que le serveur de base de données réponde sur le réseau, le temps d’exécution proprement dit des requêtes SQL une fois reçues, et le temps de traitement PHP pur, celui qui ne dépend d’aucune base de données.
Première part : la latence réseau vers MySQL
Lorsque WordPress et sa base de données ne partagent pas le même serveur physique, chaque requête effectuée via $wpdb traverse le réseau interne de l’hébergeur avant d’atteindre le moteur MySQL. Cette latence, souvent de l’ordre d’une à quelques millisecondes sur une infrastructure bien conçue, peut grimper significativement si le serveur de base de données est distant géographiquement ou surchargé. Elle se mesure en isolant une requête minimale, du type SELECT 1, chronométrée avec hrtime() juste avant et juste après son exécution :
$debut = hrtime( true );
$wpdb->get_var( 'SELECT 1' );
$latence_reseau = ( hrtime( true ) - $debut ) / 1e6; // en millisecondes
Deuxième part : le temps d’exécution des requêtes

Une fois la latence réseau connue, la différence entre le temps total rapporté par $wpdb->queries (lorsque SAVEQUERIES est activé) et cette latence de base donne une estimation du temps réellement passé par MySQL à exécuter la requête : recherche d’index, tri, jointures. C’est cette part qui bénéficie le plus d’un index bien choisi ou d’une requête réécrite. Un test comparatif mené sur une page d’archive de trois cents articles a donné les résultats suivants :
| Composante | Temps mesuré | Part du total |
|---|---|---|
| Latence réseau cumulée (18 requêtes) | 36 ms | 11 % |
| Exécution SQL cumulée | 142 ms | 44 % |
| Traitement PHP pur | 142 ms | 45 % |
Troisième part : le traitement PHP pur
Ce qui reste, une fois soustraites les deux premières parts du temps de génération total, correspond au traitement effectué par PHP sans aucun échange avec la base de données : rendu des blocs, application des filtres et des actions, formatage des dates, échappement des sorties, exécution du thème lui-même. Sur l’exemple ci-dessus, cette part représentait presque la moitié du temps total, une proportion souvent sous-estimée par des équipes qui concentrent leurs efforts d’optimisation sur les seules requêtes SQL.
Pourquoi cette décomposition change les priorités
Sur ce site précis, l’équipe technique avait initialement prévu d’ajouter un cache d’objets persistant pour réduire le temps SQL, en supposant que la base de données était le principal responsable de la lenteur. La décomposition a montré que le traitement PHP pur pesait autant que les requêtes elles-mêmes : une partie de cet effort venait de plusieurs filtres the_content appliqués séquentiellement par différentes extensions, chacune ajoutant son propre traitement du texte affiché.
Comment reproduire cette mesure sur un site
- Activer temporairement la constante
SAVEQUERIESdanswp-config.php, uniquement sur un environnement de test, jamais en production où elle ajoute elle-même un coût. - Mesurer une requête minimale de type
SELECT 1pour établir la latence réseau de référence. - Comparer le temps de génération total, rapporté par un en-tête
Server-Timingpersonnalisé, avec la somme des deux premières parts pour en déduire le temps PHP pur par soustraction.
Un temps de génération n’est jamais un bloc unique : le décomposer révèle souvent que la moitié du problème ne se trouve pas là où on la cherchait en premier.
En résumé
Séparer la latence réseau, le temps d’exécution SQL et le traitement PHP pur transforme un chiffre global, difficile à interpréter, en trois pistes de correction distinctes. Sur ce site associatif, cette décomposition a réorienté l’effort d’optimisation vers les filtres de contenu plutôt que vers un cache d’objets qui n’aurait résolu qu’une partie du problème.