vendredi 25 septembre 2026

À propos

Contact

Performance

Colonnes JSON de MySQL 8 pour des metas complexes : plus rapide que postmeta ?

Comparatif entre stocker des données structurées dans wp_postmeta classique et dans une colonne JSON native MySQL 8, mesures sur 100 000 lignes.

Par Clément Hadrot • 19 mars 2023 • 4 min de lecture • Aucun commentaire
Colonnes JSON de MySQL 8 pour des metas complexes : plus rapide que postmeta ?

Un client gérant un catalogue de pièces automobiles stockait, pour chaque produit, un ensemble de caractéristiques techniques structurées : dimensions, compatibilités moteur, certifications, sous forme d’un tableau PHP sérialisé dans un unique champ wp_postmeta. Cette approche fonctionne, mais interroger une caractéristique précise, par exemple tous les produits compatibles avec un moteur donné, demandait de charger et désérialiser ce champ pour chaque produit, en PHP, faute de pouvoir filtrer efficacement une valeur sérialisée directement en SQL.

MySQL 8 propose un type de colonne JSON natif, avec des fonctions permettant d’interroger directement une clé à l’intérieur du document stocké, sans désérialisation applicative. Ce comparatif mesure si ce type de colonne apporte un gain réel sur ce cas d’usage précis, par rapport à l’approche wp_postmeta classique.

Le protocole de test

Une table de 100 000 produits fictifs a été générée deux fois : une fois avec les caractéristiques techniques stockées en wp_postmeta sérialisé classique, une fois dans une table personnalisée avec une colonne caracteristiques de type JSON natif MySQL 8. Les deux approches ont été testées sur la même requête métier : trouver tous les produits compatibles avec un moteur « 1.6 HDi », une valeur enfouie dans la structure de données de chaque produit.

La requête côté wp_postmeta classique

Sans possibilité de filtrer directement une clé sérialisée en SQL, la seule approche viable consistait à charger l’ensemble des 100 000 lignes candidates, puis à désérialiser et filtrer côté PHP :

$resultats = array();
$tous = $wpdb->get_results( "SELECT post_id, meta_value FROM wp_postmeta WHERE meta_key = 'caracteristiques'" );

foreach ( $tous as $ligne ) {
    $donnees = maybe_unserialize( $ligne->meta_value );
    if ( in_array( '1.6 HDi', $donnees['moteurs_compatibles'] ?? array(), true ) ) {
        $resultats[] = $ligne->post_id;
    }
}

Temps mesuré pour cette requête sur les 100 000 lignes : 3,4 secondes en moyenne, l’essentiel du coût provenant de la désérialisation PHP répétée plutôt que de la lecture SQL elle-même.

L'essentiel à retenir : wp_postmeta stocke une donnée structurée sous forme sérialisée par ligne ; Une colonne JSON native permet d'interroger une clé sans tout désérialiser ; Le gain dépend fortement du type de requête, pas seulement du stockage

La requête côté colonne JSON native

Avec une colonne JSON native, la fonction JSON_CONTAINS() de MySQL permet de filtrer directement en SQL, sans jamais charger les lignes non concernées côté PHP :

SELECT id FROM produits_caracteristiques
WHERE JSON_CONTAINS(caracteristiques, '"1.6 HDi"', '$.moteurs_compatibles');

Temps mesuré pour cette requête équivalente : 420 millisecondes en moyenne, un gain net d’un facteur proche de huit par rapport à l’approche wp_postmeta. Un index fonctionnel généré à partir du chemin JSON a permis de réduire encore ce temps à 90 millisecondes, une option qui n’a pas d’équivalent simple avec des données sérialisées en wp_postmeta.

ALTER TABLE produits_caracteristiques
ADD INDEX idx_moteurs ((CAST(caracteristiques->>'$.moteurs_compatibles' AS CHAR(255)) COLLATE utf8mb4_bin));

Ce que ce gain ne dit pas de tout

Ce comparatif porte spécifiquement sur une requête de filtrage sur une valeur imbriquée. Pour un usage plus simple, comme la simple lecture de toutes les caractéristiques d’un produit déjà connu par son identifiant, l’écart entre les deux approches devient négligeable, wp_postmeta restant tout à fait adapté et surtout mieux intégré nativement à l’écosystème d’extensions WordPress qui s’attendent à cette structure de table.

Scénariowp_postmeta sérialiséColonne JSON native
Lecture d’un produit par ID2 ms2 ms
Filtrage sur une clé imbriquée, sans index3,4 s420 ms
Filtrage sur une clé imbriquée, avec index fonctionnelnon applicable90 ms

Ce qu’il faut peser avant de migrer

  • Une table personnalisée avec colonne JSON sort du modèle standard WordPress, ce qui complique l’intégration avec certaines extensions tierces.
  • Le gain n’est significatif que sur des requêtes de filtrage complexes sur des données imbriquées, pas sur une lecture simple par identifiant.
  • Un index fonctionnel sur une colonne JSON demande une maintenance et une compréhension technique supplémentaires pour l’équipe.

Notre verdict

Les colonnes JSON natives de MySQL 8 apportent un gain réel et mesurable sur des requêtes de filtrage complexes portant sur des données structurées imbriquées, au prix d’une sortie du modèle wp_postmeta standard. Ce choix se justifie surtout pour des tables personnalisées à fort volume et à requêtes de filtrage fréquentes, pas comme un remplacement systématique du système de métadonnées natif de WordPress.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi