Le Slow Query Log (journal des requêtes lentes) est un fichier de log MySQL/MariaDB qui enregistre toutes les requêtes SQL dont le temps d’exécution dépasse un seuil prédéfini. Cet outil de diagnostic permet d’identifier les requêtes problématiques impactant les performances d’un site WordPress.
Fonctionnement
Activation
-- Activer le slow query log
SET GLOBAL slow_query_log = 'ON';
-- Définir le seuil de lenteur (en secondes)
SET GLOBAL long_query_time = 2;
-- Spécifier l'emplacement du fichier de log
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow-query.log';
Configuration dans my.cnf / my.ini
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 2
log_queries_not_using_indexes = 1
log_slow_admin_statements = 1
log_slow_slave_statements = 1
Paramètres Clés
| Paramètre | Description | Valeur Typique |
|---|---|---|
| long_query_time | Seuil de durée pour considérer une requête comme « lente » | 1-2 secondes |
| log_queries_not_using_indexes | Journaliser les requêtes sans index | 1 (activé) |
| log_slow_admin_statements | Inclure les commandes administratives | 1 (activé) |
| log_slow_slave_statements | Inclure les requêtes de réplication | 0 (désactivé) |
| slow_query_log | Activer/désactiver le journal | 1 (ON) |
Format d’une Entrée de Log
# Time: 2024-01-15T14:23:45.123456Z
# User@Host: wordpress[wordpress] @ localhost []
# Thread_id: 12345 Schema: wordpress_db QC_hit: No
# Query_time: 3.456789 Lock_time: 0.000123 Rows_sent: 1000 Rows_examined: 50000
# Rows_affected: 0 Bytes_sent: 250000
SET timestamp=1705328625;
SELECT * FROM wp_posts
WHERE post_status = 'publish'
AND post_type = 'post'
ORDER BY post_date DESC;
Explication des métriques :
- Query_time : Temps total d’exécution (3.45s = lent)
- Lock_time : Temps d’attente des verrous
- Rows_sent : Lignes retournées au client
- Rows_examined : Lignes analysées par MySQL (50k = problème potentiel)
- Bytes_sent : Volume de données transférées
Cas Typiques de Requêtes Lentes dans WordPress
1. Requêtes sans Index
-- Problème : WHERE sur un champ non indexé
SELECT * FROM wp_postmeta WHERE meta_value LIKE '%recherche%';
2. Jointures Multiples
-- Problème : Trop de JOIN
SELECT p.*, u.user_nicename, c.comment_count, t.name
FROM wp_posts p
LEFT JOIN wp_users u ON p.post_author = u.ID
LEFT JOIN wp_term_relationships tr ON p.ID = tr.object_id
LEFT JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN wp_terms t ON tt.term_id = t.term_id
WHERE p.post_status = 'publish';
3. Requêtes sur wp_options
-- Problème : Options non autoloadées ou trop volumineuses
SELECT option_name, option_value FROM wp_options
WHERE autoload = 'yes'
AND option_value LIKE '%serialized_data%';
4. Requêtes de Recherche
-- Problème : LIKE avec wildcard en début
SELECT * FROM wp_posts
WHERE post_title LIKE '%motclef%'
OR post_content LIKE '%motclef%';
Outils d’Analyse
mysqldumpslow (Outil MySQL natif)
# Afficher les requêtes les plus lentes
mysqldumpslow -s t /var/log/mysql/slow-query.log
# Top 10 des requêtes par temps moyen
mysqldumpslow -s at -t 10 /var/log/mysql/slow-query.log
# Regrouper par requête similaire
mysqldumpslow -g 'SELECT.*wp_posts' /var/log/mysql/slow-query.log
pt-query-digest (Percona Toolkit)
# Analyse détaillée avec statistiques
pt-query-digest /var/log/mysql/slow-query.log > analyse.txt
# Analyse en temps réel
pt-query-digest --processlist h=localhost,u=root,p=password
Plugins WordPress
- Query Monitor – Analyse en temps réel des requêtes
- Debug Bar – Barre de débogage avec stats SQL
- New Relic – Monitoring APM complet
Bonnes Pratiques d’Optimisation
1. Ajouter des Index
-- Index sur wp_postmeta pour les requêtes fréquentes
CREATE INDEX meta_key_value ON wp_postmeta(meta_key, meta_value(191));
-- Index sur wp_comments pour le statut
CREATE INDEX comment_approved ON wp_comments(comment_approved);
2. Limiter les Résultats
// Mauvais : récupérer tout
$posts = get_posts(array('numberposts' => -1));
// Bon : pagination
$posts = get_posts(array('posts_per_page' => 20));
3. Utiliser le Cache
// Transient API pour les requêtes coûteuses
$expensive_data = get_transient('my_expensive_query');
if (false === $expensive_data) {
$expensive_data = ma_requete_couteuse();
set_transient('my_expensive_query', $expensive_data, DAY_IN_SECONDS);
}
4. Éviter les Requêtes N+1
// Mauvais : requête dans boucle
foreach ($posts as $post) {
$author = get_userdata($post->post_author); // Requête à chaque itération
}
// Bon : récupérer tous les auteurs en une fois
$author_ids = wp_list_pluck($posts, 'post_author');
$authors = get_users(array('include' => array_unique($author_ids)));
Seuils de Performance Recommandés
| Type de Site | long_query_time | Action Requise |
|---|---|---|
| Blog personnel | 2s | > 5s = investiguer |
| Site d’entreprise | 1s | > 2s = optimiser |
| E-commerce | 0.5s | > 1s = critique |
| High-traffic | 0.1s | > 0.5s = urgence |
Impact sur WordPress
Un Slow Query Log bien configuré permet de :
- Identifier les goulots d’étranglement
- Mesurer l’impact des plugins/themes
- Optimiser les performances globales
- Réduire les coûts d’hébergement
- Prévenir les problèmes de scalabilité
Workflow de Diagnostic Recommandé
- Activer le slow query log (long_query_time = 1)
- Laisser tourner 24-48h en production
- Analyser avec pt-query-digest
- Prioriser les requêtes par impact cumulé
- Optimiser les requêtes problématiques
- Tester en staging avant production
- Surveiller l’amélioration des performances