# Optimiser les tables MySQL de WordPress : InnoDB, index et nettoyage

> Convertir les tables en InnoDB, ajouter les bons index sur les metas, purger les transients expirés : la maintenance qui rend une base WordPress rapide.

- Auteur : Clément Hadrot
- Publié le : 2020-04-17
- Mis à jour le : 2020-04-17
- Catégorie : Performance
- URL : https://wpmoderne.dev.wordpress-developpement.fr/performance/optimiser-tables-mysql-wordpress-innodb-index/

## L’essentiel

- MyISAM verrouille toute la table, InnoDB verrouille la ligne
- Deux index composites suffisent souvent sur postmeta
- OPTIMIZE TABLE récupère l'espace fragmenté

Un client reprenait un site vieux de six ans, migré d'hébergeur en hébergeur sans jamais toucher à la base de données. Les temps de réponse grimpaient dès que deux visiteurs cherchaient un produit en même temps. En regardant le moteur de stockage des tables avec `SHOW TABLE STATUS`, la cause est apparue immédiatement : la moitié des tables étaient encore en MyISAM.

La base de données est souvent la grande oubliée des audits de performance WordPress, qui se concentrent sur le cache et les images. Pourtant, une table mal indexée ou un moteur de stockage inadapté peuvent faire plus de dégâts qu'une image trop lourde. Voici la remise à niveau que nous appliquons sur les bases anciennes.

## MyISAM contre InnoDB : une différence qui se voit sous charge

WordPress installe ses tables en InnoDB depuis la version 5.5 de MySQL recommandée, mais de nombreuses bases anciennes traînent encore des tables MyISAM, héritées d'une migration ou d'une extension mal codée. Le problème de MyISAM n'est pas visible avec un seul visiteur : il se révèle dès que plusieurs écritures concurrentes surviennent, parce que ce moteur verrouille la table entière à chaque écriture, alors qu'InnoDB verrouille uniquement la ligne concernée.

Sur un site avec des commentaires actifs, un système de réservation ou WooCommerce, ce verrou de table entière crée des files d'attente invisibles qui font grimper le TTFB sans qu'aucune requête individuelle ne soit lente. La conversion se fait table par table :

```
ALTER TABLE wp_options ENGINE=InnoDB;
ALTER TABLE wp_postmeta ENGINE=InnoDB;
ALTER TABLE wp_usermeta ENGINE=InnoDB;
```

Sur une grosse base, chaque `ALTER TABLE` verrouille la table le temps de la conversion : planifiez cette opération hors heures de pointe, et pas en pleine campagne commerciale.

## Les index qui manquent presque toujours sur postmeta

La table `wp_postmeta` est structurée en clé-valeur : chaque ligne associe un `post_id`, une `meta_key` et une `meta_value`. Par défaut, WordPress index bien la colonne `meta_key`, mais dès qu'une requête filtre sur une clé précise **et** trie ou filtre encore sur sa valeur, l'absence d'index composite oblige MySQL à parcourir des milliers de lignes.

> L'essentiel à retenir : MyISAM verrouille toute la table, InnoDB verrouille la ligne ; Deux index composites suffisent souvent sur postmeta ; OPTIMIZE TABLE récupère l'espace fragmenté

Un cas fréquent : une boutique qui filtre ses produits par une meta de stock ou de prix personnalisée. Un index composite sur `(meta_key, meta_value(20))` change radicalement le plan d'exécution :

```
CREATE INDEX idx_meta_key_value ON wp_postmeta (meta_key, meta_value(20));
```

Vérifiez toujours avec `EXPLAIN` avant et après pour vous assurer que MySQL utilise réellement le nouvel index plutôt que de continuer un balayage complet :

```
EXPLAIN SELECT post_id FROM wp_postmeta
WHERE meta_key = 'stock_status' AND meta_value = 'instock';
```

## Nettoyer les transients expirés

Les transients sont censés expirer tout seuls, mais WordPress ne les supprime réellement que lorsqu'ils sont lus après expiration, ou via le nettoyage planifié. Sur une base jamais entretenue, il n'est pas rare de trouver des dizaines de milliers de lignes de transients périmés dans `wp_options`, ce qui alourdit chaque requête qui balaie cette table.

WP-CLI propose une commande dédiée, bien plus sûre qu'une requête SQL manuelle :

```
wp transient delete --expired
wp transient delete --all
```

La seconde commande est plus radicale : elle supprime aussi les transients encore valides, ce qui force leur régénération. Utile ponctuellement après une migration, à éviter en routine sur un site à fort trafic.

## OPTIMIZE TABLE : récupérer l'espace fragmenté

Après des années de suppressions et de mises à jour, les tables InnoDB accumulent de la fragmentation interne : l'espace disque occupé ne correspond plus aux données réellement présentes. La commande `OPTIMIZE TABLE` reconstruit la table et récupère cet espace :

```
OPTIMIZE TABLE wp_options, wp_postmeta, wp_usermeta;
```

Sur InnoDB, cette opération recopie toute la table dans un fichier temporaire : elle peut prendre du temps sur une table volumineuse et nécessite de l'espace disque disponible. Elle réduit rarement le temps de réponse d'une requête isolée, mais elle diminue la taille des sauvegardes et améliore l'efficacité du cache mémoire de MySQL, qui tient alors plus de données utiles par giga-octet alloué.

## Une checklist de maintenance trimestrielle

- Vérifier le moteur de stockage de chaque table avec `SHOW TABLE STATUS` et convertir ce qui reste en MyISAM.
- Repérer les requêtes lentes récurrentes et vérifier qu'un index composite ne manque pas sur `postmeta` ou `usermeta`.
- Purger les transients expirés avec `wp transient delete --expired`.
- Lancer `OPTIMIZE TABLE` sur les tables les plus volumineuses, hors heures de forte charge.

> Une base de données WordPress bien entretenue se voit surtout à ce qu'on n'y remarque rien : pas de pic de lenteur inexpliqué les jours de forte affluence.

## Notre verdict

Ces quatre gestes ne remplacent pas un cache de page ni un bon hébergement, mais ils évitent qu'une base de données mal entretenue vienne ruiner tous les efforts faits ailleurs. Ils demandent peu de temps, ne nécessitent aucune extension supplémentaire, et méritent une place dans la routine de maintenance de tout site WordPress qui dépasse quelques années d'existence.
