Combien de requêtes SQL faut-il réellement pour afficher un catalogue d’une centaine de cuvées, avec leur appellation, leur millésime et leur disponibilité en stock ? La réponse, avant audit, était 218 sur le site d’une coopérative viticole qui commercialise sa production directement en ligne. Après correctif, elle est tombée à 96, sans qu’aucune fonctionnalité n’ait été retirée.
Le point de départ : une page de catalogue anormalement gourmande
Le catalogue affichait chaque cuvée sous forme de fiche synthétique, avec cinq champs personnalisés Advanced Custom Fields par produit : appellation, millésime, degré d’alcool, disponibilité, et accord mets-vins recommandé. Rien d’exceptionnel en soi, mais le nombre de requêtes générées pour une centaine de fiches affichées sur une seule page laissait supposer un problème d’architecture plutôt qu’un simple volume de données.
L’outil Query Monitor, activé temporairement sur un environnement de préproduction identique à la production, a permis de visualiser précisément l’origine de chaque requête exécutée pendant le chargement de la page.
Le diagnostic : un appel à get_field répété sans cache
La boucle d’affichage du catalogue appelait la fonction get_field() d’Advanced Custom Fields cinq fois par produit, une fois par champ personnalisé, sans qu’aucun mécanisme ne regroupe ces lectures. Chaque appel déclenchait sa propre requête vers la table wp_postmeta, faute d’avoir été préalablement chargé en une seule fois.

// Avant : cinq requêtes par produit dans la boucle
foreach ( $produits as $produit ) {
$appellation = get_field( 'appellation', $produit->ID );
$millesime = get_field( 'millesime', $produit->ID );
$degre = get_field( 'degre_alcool', $produit->ID );
$stock = get_field( 'disponibilite', $produit->ID );
$accord = get_field( 'accord_mets_vins', $produit->ID );
}
Sur cent produits, ce schéma génère à lui seul cinq cents requêtes potentielles, en partie atténuées par le cache interne d’ACF au sein d’une même requête HTTP, mais sans que ce cache élimine totalement la redondance constatée.
Le correctif : précharger les métadonnées en un seul appel
La solution retenue consiste à précharger l’ensemble des métadonnées des produits affichés en une seule requête groupée, via la fonction native update_meta_cache(), avant de parcourir la boucle d’affichage :
$ids_produits = wp_list_pluck( $produits, 'ID' );
update_meta_cache( 'post', $ids_produits );
foreach ( $produits as $produit ) {
// get_field() lit désormais depuis le cache déjà chargé,
// sans déclencher de nouvelle requête par champ
$appellation = get_field( 'appellation', $produit->ID );
// ...
}
Ce préchargement regroupe en une seule requête ce qui nécessitait auparavant un aller-retour par champ et par produit, une pratique directement recommandée par la documentation de l’API WordPress pour tout affichage en boucle de métadonnées.
Le résultat mesuré et sa portée
- Nombre de requêtes SQL sur la page de catalogue : de 218 à 96
- Temps de génération de la page, hors cache de page : de 1,8 s à 0,7 s
- Aucune modification visible côté visiteur, le correctif restant purement structurel
Un audit de performance qui ne cherche pas d’abord les boucles de champs personnalisés passe généralement à côté du problème le plus fréquent et le plus facile à corriger.
En résumé
Le problème rencontré par cette coopérative viticole reste l’un des plus classiques de l’écosystème WordPress dès qu’Advanced Custom Fields entre en jeu dans une boucle d’affichage. Le préchargement des métadonnées, simple à mettre en œuvre, a divisé par plus de deux le nombre de requêtes générées. Ce billet ne traite pas du référencement du catalogue, qui reste un sujet distinct de la seule question du nombre de requêtes exécutées.