# Indexer la table wp_options pour accélérer la lecture des réglages autoload sur un cluster mutualisé

> Un index composite bien choisi sur wp_options peut réduire drastiquement le coût d'une requête exécutée sur chaque chargement de page, à volume d'options inchangé.

- Auteur : WordPress Développement
- Publié le : 2023-09-07
- Mis à jour le : 2023-09-07
- Catégorie : Hébergement &amp; serveurs
- URL : https://www.wpmoderne.fr/hebergement/index-wp-options-autoload-cluster-mutualise/

## L’essentiel

- la requête autoload s'exécute à chaque chargement de page WordPress
- un index composite adapté cible exactement le filtre utilisé
- l'effet se mesure surtout sur des bases dépassant plusieurs milliers d'options

`SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'` : cette requête, générée par le cœur de WordPress à chaque chargement de page via la fonction interne `wp_load_alloptions()`, s'exécute des dizaines de milliers de fois par jour sur un cluster mutualisé hébergeant plusieurs centaines de bases WordPress.

Ce billet documente l'ajout d'un index composite adapté à ce filtre précis, sur un cluster où plusieurs bases dépassaient les dix mille lignes dans `wp_options`, sans que la réduction du volume d'options autoloadées elle-même n'ait encore pu être menée, faute de temps disponible côté équipe applicative.

## Pourquoi cette requête pèse plus qu'il n'y paraît

La fonction `wp_load_alloptions()` charge en une seule fois toutes les options marquées `autoload = 'yes'` et les place en cache d'objet pour le reste de l'exécution de la page. Sur un site bien tenu, ce jeu de données reste limité à quelques centaines de lignes. Mais un nombre croissant d'extensions marquent leurs propres réglages en autoload par défaut, sans que l'administrateur du site n'en ait toujours conscience, et ce volume grossit silencieusement au fil des installations d'extensions successives.

Sans index adapté au filtre sur `autoload`, MySQL doit parcourir l'intégralité de la table pour isoler les lignes concernées, un balayage complet dont le coût croît linéairement avec le nombre total de lignes de la table, autoloadées ou non. Sur la base la plus chargée du cluster observé, cette requête consommait en moyenne 340 millisecondes avant intervention, un délai qui s'ajoutait à chaque chargement de page, y compris pour un simple article de blog sans logique métier complexe.

## L'index composite qui cible exactement ce filtre

La table `wp_options` possède nativement un index sur `option_name`, mais aucun index par défaut sur la colonne `autoload` seule. L'ajout d'un index composite couvrant à la fois `autoload` et les colonnes lues par la requête permet à MySQL de répondre directement depuis l'index, sans accéder aux lignes complètes de la table.

```
ALTER TABLE wp_options
  ADD INDEX autoload_options (autoload, option_id);
```

Ce choix d'index, volontairement restreint à `autoload` et à la clé primaire `option_id`, évite de dupliquer inutilement le contenu potentiellement volumineux d'`option_value` dans l'index lui-même, ce qui aurait alourdi les écritures sans bénéfice proportionné en lecture.

> L'essentiel à retenir : la requête autoload s'exécute à chaque chargement de page WordPress ; un index composite adapté cible exactement le filtre utilisé ; l'effet se mesure surtout sur des bases dépassant plusieurs milliers d'options

## Vérifier l'effet réel avec EXPLAIN avant et après

Avant toute application sur le cluster de production, la commande `EXPLAIN` a permis de confirmer que le plan d'exécution utilisait bien le nouvel index plutôt que de continuer à balayer la table intégralement, un point qui n'est jamais garanti automatiquement selon la répartition des valeurs de la colonne indexée.

- Avant l'index : type `ALL` dans le plan d'exécution, balayage complet de la table, coût proportionnel à son volume total.
- Après l'index : type `ref`, utilisation directe de l'index `autoload_options`, coût proportionnel au seul sous-ensemble des lignes autoloadées.
- Le gain observé sur la base la plus chargée du cluster a fait passer le temps moyen de la requête de 340 millisecondes à moins de 15 millisecondes, sans aucune modification côté applicatif.

## Ce que cet index ne résout pas

Cette intervention agit exclusivement sur le coût de lecture de la requête, pas sur le volume de données transférées et mises en cache d'objet à chaque exécution. Une base avec quinze mille lignes autoloadées continuera de transférer un volume important de données à chaque chargement de page, même avec un index parfaitement adapté au filtre. La réduction de ce volume, en identifiant les extensions qui autoloadent des réglages volumineux sans nécessité réelle, reste un chantier distinct, non traité ici.

> Un index accélère l'accès à des données ; il ne réduit jamais leur volume. Les deux chantiers sont complémentaires, rarement substituables l'un à l'autre.

## Déploiement prudent sur un cluster mutualisé

L'ajout de cet index a été déployé progressivement, base par base, plutôt qu'en un script global appliqué à l'ensemble du cluster en une seule opération. Sur MySQL 8, l'opération `ALTER TABLE ... ADD INDEX` s'exécute en ligne par défaut sans verrouillage bloquant prolongé sur cette table de petite taille relative, mais la prudence a primé sur un cluster où chaque base sert un client de production différent, avec des contraintes de disponibilité propres.

## En résumé

Un index composite ciblant précisément le filtre `autoload = 'yes'` a permis de diviser par plus de vingt le temps de la requête la plus fréquemment exécutée par WordPress sur ce cluster, sans toucher au code applicatif ni réduire le volume de réglages autoloadés. Cette intervention, simple et peu risquée, ne dispense toutefois pas d'un travail complémentaire sur le volume d'options lui-même, seul capable de réduire durablement la quantité de données transférées à chaque chargement de page.
