Journal

MySQL 8 : les fonctionnalités à ne plus ignorer

Journal du mercredi 26 août 2026, généré le 26 août à 21:48

Un nouveau cycle de versions depuis 2024

Depuis MySQL 8.4, Oracle a changé son modèle de release : il existe désormais des versions Innovation (nouvelles fonctionnalités, support court) et des versions LTS comme 8.4, maintenues plusieurs années. En production, il vaut mieux rester sur une LTS et ne migrer vers une Innovation que pour tester une fonctionnalité précise avant qu'elle n'atterrisse dans la LTS suivante.

CTE récursives et fonctions de fenêtrage

Depuis MySQL 8.0, les Common Table Expressions récursives permettent de parcourir des structures arborescentes sans boucle applicative, par exemple une hiérarchie de catégories :

WITH RECURSIVE arbre AS (
  SELECT id, nom, parent_id, 0 AS niveau
  FROM categories WHERE parent_id IS NULL
  UNION ALL
  SELECT c.id, c.nom, c.parent_id, a.niveau + 1
  FROM categories c
  JOIN arbre a ON c.parent_id = a.id
)
SELECT * FROM arbre ORDER BY niveau;

Combinées aux fonctions de fenêtrage (RANK(), ROW_NUMBER(), SUM() OVER (...)), elles évitent des sous-requêtes corrélées coûteuses, par exemple pour classer les commandes par client sans GROUP BY destructeur.

Exemple de classement par partition

SELECT client_id, montant,
       RANK() OVER (PARTITION BY client_id ORDER BY montant DESC) AS rang
FROM commandes;

Index invisibles : tester avant de supprimer

Un index invisible reste maintenu par le moteur mais n'est plus utilisé par l'optimiseur. C'est le moyen le plus sûr de vérifier qu'un index est réellement mort avant de le droper :

ALTER TABLE commandes ALTER INDEX idx_statut INVISIBLE;
-- observer les plans d'exécution et les métriques pendant quelques jours
ALTER TABLE commandes DROP INDEX idx_statut;

JSON natif et colonnes générées

Le type JSON stocke une valeur validée et binaire, interrogeable via JSON_TABLE() pour transformer un document en lignes relationnelles, ou via des expressions paths comme ->>. Pour indexer un champ JSON fréquemment filtré, on crée une colonne générée stockée puis un index dessus :

ALTER TABLE evenements
  ADD COLUMN type_evt VARCHAR(50)
  GENERATED ALWAYS AS (payload->>'$.type') STORED,
  ADD INDEX idx_type_evt (type_evt);

Points de vigilance

  • utf8mb4 doit être le jeu de caractères par défaut de toute nouvelle base, pas utf8 (limité à 3 octets, incompatible emojis).
  • Le moteur InnoDB est désormais quasi systématique : vérifier qu'aucune table historique n'utilise encore MyISAM, notamment pour les tables de verrouillage transactionnel.
  • La réplication basée sur GTID facilite le failover ; privilégier SOURCE_AUTO_POSITION plutôt que la coordonnée binlog/position, plus fragile.