# Un index MySQL composite manquant : le test de performance qui le révèle

> Une requête WP_Query complexe ralentit progressivement avec le volume de données. Un test de performance dédié détecte l'absence d'un index composite avant qu'elle ne devienne un problème visible.

- Auteur : Clément Hadrot
- Publié le : 2026-02-28
- Mis à jour le : 2026-02-28
- Catégorie : Tests
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tests/index-mysql-composite-manquant-test-performance/

## L’essentiel

- Un test fonctionnel classique ne détecte jamais un problème de performance, seulement un résultat correct
- Un test de performance dédié compare un temps d'exécution à un seuil explicite, pas à un résultat attendu
- L'absence d'index composite se révèle par une dégradation proportionnelle au volume, pas par un résultat faux

340 millisecondes pour une requête qui recense les événements à venir d'une association culturelle, filtrés par catégorie et triés par date : ce chiffre, mesuré volontairement dans un test de performance dédié plutôt que découvert en production, a permis d'identifier l'absence d'un index composite avant qu'aucun client ne s'en aperçoive.

La requête concernée, construite via `WP_Query` avec une combinaison de `meta_query` et de tri par date, fonctionnait correctement à faible volume de données : les résultats retournés étaient exacts, ce qui expliquait pourquoi aucun test fonctionnel classique n'avait jamais signalé de problème. Le ralentissement n'apparaît qu'à mesure que le nombre de lignes de la table de métadonnées augmente, un phénomène qu'un test de résultat correct ne peut, par construction, jamais détecter.

## Pourquoi un test fonctionnel ne suffit pas ici

Un test qui vérifie qu'une requête retourne les bons événements, dans le bon ordre, reste vert indépendamment du temps d'exécution nécessaire pour y parvenir. Sur un jeu de données de test réduit à quelques dizaines de lignes, l'absence d'index composite ne se traduit par aucune différence de résultat, seulement par un temps de réponse plus long, invisible tant que le volume reste faible.

## Construire un test qui mesure, pas seulement qui vérifie

> L'essentiel à retenir : Un test fonctionnel classique ne détecte jamais un problème de performance, seulement un résultat correct ; Un test de performance dédié compare un temps d'exécution à un seuil explicite, pas à un résultat attendu ; L'absence d'index composite se révèle par une dégradation proportionnelle au volume, pas par un résultat faux

Le test de performance ajouté crée délibérément un volume de données représentatif, cinq mille événements avec leurs métadonnées associées, puis mesure le temps d'exécution de la requête concernée contre un seuil explicite :

```
public function laRechercheDEvenementsRestePerformanteAVolumeEleve(): void
{
    for ($i = 0; $i < 5000; $i++) {
        $id = self::factory()->post->create(['post_type' => 'evenement_association']);
        update_post_meta($id, 'categorie_evenement', $i % 12 === 0 ? 'atelier' : 'conference');
        update_post_meta($id, 'date_evenement', gmdate('Y-m-d', strtotime("+{$i} days")));
    }

    $debut = microtime(true);
    $requete = new \WP_Query([
        'post_type' => 'evenement_association',
        'meta_key' => 'categorie_evenement',
        'meta_value' => 'atelier',
        'orderby' => 'meta_value',
        'meta_key2' => 'date_evenement',
        'posts_per_page' => 20,
    ]);
    $duree_ms = (microtime(true) - $debut) * 1000;

    $this->assertLessThan(50, $duree_ms, "Requête trop lente : {$duree_ms} ms");
}
```

Ce test a échoué à sa première exécution, avec une durée mesurée de 340 millisecondes, très au-dessus du seuil de 50 millisecondes fixé.

### Ce que le plan d'exécution MySQL a confirmé

La commande `EXPLAIN` exécutée sur la requête générée par `WP_Query` a confirmé l'absence d'index adapté à la combinaison des deux clés de métadonnées utilisées conjointement pour le filtrage et le tri, forçant MySQL à parcourir une part importante de la table `wp_postmeta` pour chaque exécution.

## La correction, côté base de données

La création de l'index composite lui-même, adapté à cette combinaison précise de colonnes, relève d'une décision de structure de base de données distincte de ce test : ce dernier se contente de la déclencher en révélant le besoin, sans imposer la structure exacte de l'index à créer. Une fois l'index approprié ajouté par l'équipe responsable du schéma, le même test est repassé à 12 millisecondes, bien en dessous du seuil fixé.

- Le seuil de 50 millisecondes a été choisi en fonction du volume attendu à trois ans, pas du volume actuel du site en production.
- Le test recrée son propre volume de données à chaque exécution, sans dépendre d'un état préexistant de la base de test.
- Un tel test reste coûteux en temps d'exécution CI : il est isolé dans un groupe dédié, lancé moins fréquemment que la suite fonctionnelle principale.

> Un résultat juste ne dit rien du temps qu'il a fallu pour l'obtenir ; seul un test qui mesure ce temps peut le révéler avant qu'un volume réel ne le fasse à la place.

## En résumé

Un test de performance dédié, qui compare un temps d'exécution mesuré à un seuil explicite plutôt que de vérifier un simple résultat, a révélé l'absence d'un index composite sur une requête WP_Query combinant filtrage et tri par métadonnées. Le passage de 340 à 12 millisecondes après ajout de l'index confirme que ce type de test détecte une classe de problèmes qu'aucun test fonctionnel classique ne peut, par nature, mettre en évidence.
