Un phénomène classique : un site est rapide les premiers mois, puis ralentit progressivement sans qu’aucune ligne de code n’ait changé. La cause la plus fréquente est simple : la base de données a grossi, et des requêtes rapides sur peu de données deviennent lentes sur beaucoup de données. La bonne nouvelle, c’est que le diagnostic est méthodique et que la correction ne demande généralement pas de tout reconstruire.

Pourquoi une requête ralentit avec le volume

Une requête qui doit parcourir toute une table pour trouver quelques lignes (par exemple, rechercher un client par son e-mail sans index sur cette colonne) prend un temps à peu près proportionnel au nombre de lignes. Avec cent lignes, la différence est invisible ; avec cent mille, elle devient perceptible ; avec un million, elle peut rendre une page inutilisable.

Trouver les requêtes lentes

Avant de corriger, il faut savoir lesquelles corriger. MySQL et MariaDB peuvent enregistrer toutes les requêtes qui dépassent une durée donnée, dans le journal des requêtes lentes :

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;  -- en secondes

Après quelques heures d’utilisation normale, ce journal donne la liste des coupables, avec leur fréquence. Côté application, des outils comme Laravel Debugbar, le profileur de Symfony ou Query Monitor pour WordPress montrent les requêtes de chaque page.

Comprendre une requête avec EXPLAIN

La commande EXPLAIN montre comment MySQL exécute une requête, et s’il utilise un index :

EXPLAIN SELECT * FROM commandes WHERE client_email = 'nom@exemple.tn';

Dans le résultat, trois colonnes suffisent pour commencer : type (la valeur ALL signifie que toute la table est parcourue), key (l’index utilisé, vide s’il n’y en a pas) et rows (le nombre de lignes que MySQL pense devoir examiner). Un ALL sur une grosse table, avec une colonne key vide, désigne presque toujours un index manquant.

Le rôle des index

Un index fonctionne comme le sommaire d’un livre : au lieu de parcourir chaque page, la base va directement à l’endroit concerné.

CREATE INDEX idx_commandes_email ON commandes (client_email);

Ajouter un index sur les colonnes utilisées dans les recherches, les jointures et les tris les plus fréquents peut diviser un temps de réponse par dix ou plus, sans changer une ligne de code. Pour une recherche sur plusieurs colonnes à la fois (par exemple le statut et la date), un index composé sur les deux est plus efficace que deux index séparés, et l’ordre des colonnes compte : celle utilisée pour filtrer en premier.

Les pièges qui empêchent d’utiliser un index

Un index n’est pas gratuit

Chaque index accélère la lecture mais ralentit légèrement l’écriture, et occupe de l’espace disque. La bonne pratique consiste à indexer les colonnes réellement utilisées pour filtrer, joindre ou trier, et à supprimer les index qui ne servent jamais, pas à indexer systématiquement toutes les colonnes.

Anticiper plutôt que subir

Un site conçu dès le départ avec des index cohérents avec ses recherches réelles évite la plupart de ces ralentissements. Pour un projet déjà en production, un audit ciblé sur les requêtes les plus fréquentes suffit généralement à retrouver des temps de réponse corrects. Et avant toute modification de structure sur une base en production, une sauvegarde vérifiée (voir la règle des sauvegardes).

La check-list

  1. Activer le journal des requêtes lentes et relever les plus fréquentes.
  2. Passer chacune dans EXPLAIN : repérer les ALL et les index absents.
  3. Ajouter les index utiles, composés si la recherche porte sur plusieurs colonnes.
  4. Corriger les requêtes qui empêchent l’usage d’un index (fonctions, jokers).
  5. Supprimer les requêtes en boucle avec le chargement anticipé.
  6. Mesurer à nouveau, et supprimer les index inutilisés.

Pour aller plus loin : mon expertise : Développeur SQL / MySQL freelance · à lire aussi : Sauvegardes de base de données : la règle que presque personne ne respecte