200 000 profils de donateurs, des dizaines de critères de segmentation combinables (montant cumulé, fréquence de don, dernière campagne touchée, mode de paiement), et une exigence claire de l’association cliente : les requêtes de segmentation doivent rester utilisables au quotidien par l’équipe de collecte, même en pleine croissance de la base. Le vrai risque n’était pas fonctionnel, mais une dégradation progressive des temps de réponse, invisible tant que les tests tournaient sur un jeu de données de quelques dizaines de profils.
Cet article couvre uniquement la vérification des temps de requête de segmentation en environnement de test, pas l’architecture de la base de données elle-même, déjà traitée dans un article dédié à la catégorie extensions.
Étape 1 — Générer un jeu de données représentatif
Un test de performance sur dix profils fictifs ne dit rien du comportement réel à 200 000 lignes. Une commande WP-CLI personnalisée génère un jeu de données synthétique mais statistiquement représentatif, avec une distribution réaliste des montants et des dates de don :
wp donateurs generer-jeu-test --nombre=200000 --seed=42
Le paramètre de graine (seed) garantit que le jeu de données généré reste identique d’une exécution à l’autre, ce qui est indispensable pour comparer des temps de réponse dans la durée sans variation due au hasard de la génération.
Étape 2 — Isoler les requêtes de segmentation à surveiller

Six requêtes de segmentation ont été identifiées comme critiques par l’équipe de collecte : donateurs actifs sur les douze derniers mois, gros donateurs par tranche de montant, donateurs d’une campagne précise n’ayant pas redonné depuis, et trois combinaisons de ces critères entre eux. Chacune fait l’objet d’un test dédié plutôt que d’une mesure globale, pour identifier précisément laquelle se dégrade en cas de régression.
public function test_segmentation_gros_donateurs_sous_le_seuil(): void
{
$debut = microtime(true);
$requete = new WP_Query([
'post_type' => 'don',
'meta_query' => [
['key' => 'montant_cumule', 'value' => 500, 'compare' => '>=', 'type' => 'NUMERIC'],
],
'posts_per_page' => 100,
]);
$duree_ms = (microtime(true) - $debut) * 1000;
$this->assertLessThan(800, $duree_ms);
}
Étape 3 — Fixer un seuil explicite, pas une simple observation
Un test de performance qui se contente d’afficher un temps sans l’opposer à un seuil ne protège de rien : il faut relire le résultat à chaque fois pour juger s’il est acceptable. Sur ce projet, un seuil de 800 millisecondes par requête de segmentation a été fixé avec l’équipe technique, en cohérence avec l’exigence d’usage quotidien exprimée par l’équipe de collecte.
| Requête de segmentation | Temps mesuré | Seuil |
|---|---|---|
| Donateurs actifs 12 mois | 210 ms | 800 ms |
| Gros donateurs par tranche | 340 ms | 800 ms |
| Campagne sans redon | 1 240 ms | 800 ms |
| Combinaison des trois critères | 1 890 ms | 800 ms |
Cette table, produite lors de la première exécution à pleine échelle, a immédiatement révélé que deux requêtes sur quatre dépassaient largement le seuil retenu, alors qu’elles passaient sans souci sur le jeu de données réduit utilisé jusque-là par l’équipe.
Étape 4 — Corriger la cause, pas le symptôme
La requête de campagne sans redon combinait une meta_query sur deux critères non indexés avec une jointure implicite sur la table des dons. L’ajout d’un index composite sur les colonnes concernées, plutôt qu’une simple augmentation du seuil accepté, a ramené le temps de réponse sous la limite fixée :
ALTER TABLE wp_dons_meta
ADD INDEX idx_campagne_montant (meta_key, meta_value(20));
Augmenter artificiellement le seuil pour faire passer le test aurait masqué un vrai problème de performance qui se serait aggravé avec la croissance continue de la base de donateurs.
Étape 5 — Isoler ces tests du reste de la suite
Générer 200 000 profils à chaque exécution de la CI aurait ralenti inutilement l’ensemble de la suite pour des tests qui n’ont pas besoin de ce volume. Ces tests de performance sont regroupés dans un groupe PHPUnit dédié, exécuté une fois par nuit plutôt qu’à chaque merge :
vendor/bin/phpunit --group=performance-segmentation
- Suite principale : exécutée à chaque merge, fixtures légères, quelques secondes
- Suite de performance : exécutée nocturnement, jeu de données à pleine échelle, quelques minutes
Un test de performance qui tourne à chaque merge sur un volume complet ralentit tout le monde ; un test de performance qui ne tourne jamais ne protège personne. Le compromis nocturne donne un signal rapide sans casser le rythme de la CI quotidienne.
En résumé
Passer le cap des 200 000 donateurs a révélé deux requêtes de segmentation sur quatre au-delà du seuil acceptable, invisibles sur les jeux de données réduits utilisés jusque-là. Générer un volume représentatif, fixer un seuil explicite par requête et isoler ces tests lourds dans une exécution nocturne a permis de garder un signal fiable sans dégrader le confort quotidien de la CI.