12k
All articles

5 fonctionnalités de MariaDB qui méritent votre attention

Fonctionnalités MariaDB à connaître: recherche vectorielle, tables versionnées, périodes applicatives, moteurs par table et utf8mb4 par défaut en 11.8 LTS.

OpenReplay Team
OpenReplay Team
5 fonctionnalités de MariaDB qui méritent votre attention

Les cinq fonctionnalités de MariaDB les plus déterminantes pour une équipe exploitant MySQL 8.0 sont la recherche vectorielle intégrée, les tables versionnées par le système (system-versioned tables), les périodes de temps applicatif (application-time periods), le choix du moteur de stockage table par table, et un jeu de caractères utf8mb4 par défaut côté serveur avec les collations UCA 14.0.0 — en place depuis MariaDB 11.6 et repris par la branche LTS 11.8.

Si vous envisagez un changement de version sur un parc MySQL 8.0, MariaDB fait partie des options à inscrire sur la liste.

Ce qui suit passe en revue chaque fonctionnalité : son rôle et le SQL que vous seriez amené à écrire. Les références de version pointent vers MariaDB 11.8 LTS et MariaDB 12.3 LTS, la version que la plupart des équipes qui démarrent aujourd’hui installeraient.

À retenir

  • MariaDB embarque la recherche par similarité vectorielle directement dans le serveur communautaire : une colonne VECTOR(N) et un VECTOR INDEX reposant sur un algorithme HNSW modifié, sans aucune extension à installer.
  • MariaDB n’utilise l’index vectoriel que si la clause ORDER BY est un simple appel de fonction de distance correspondant à la métrique avec laquelle l’index a été construit, suivi d’un LIMIT ; une fonction de distance non concordante entraîne un repli sur un parcours complet de la table.
  • WITH SYSTEM VERSIONING associé à SELECT ... FOR SYSTEM_TIME AS OF vous offre des requêtes à un instant donné sans triggers d’audit ni table d’historique parallèle.
  • PERIOD FOR déclare une validité métier sur une table, et déclarer à la fois le versionnement système et une période de temps applicatif rend la table bitemporelle.
  • Le jeu de caractères par défaut est utf8mb4 depuis MariaDB 11.6, avec des collations basées sur UCA 14.0.0, et 11.8 est la première version à support long terme à en bénéficier.

Comment MariaDB fait-il de la recherche vectorielle sans extension ?

MariaDB stocke et interroge les embeddings directement dans le serveur communautaire : une colonne VECTOR(N), un VECTOR INDEX s’appuyant sur un algorithme HNSW modifié, et des fonctions de distance pour les similarités cosinus et euclidienne. La page du projet MariaDB Vector situe la disponibilité générale en 11.8 LTS, et la référence du type VECTOR plafonne une colonne à 16 383 dimensions. Rien de plus à installer, et aucun second datastore ne vient s’installer à côté de vos lignes en attendant de se désynchroniser d’elles.

CREATE TABLE support_articles (
  id         BIGINT UNSIGNED PRIMARY KEY,
  tenant_id  INT NOT NULL,
  body       TEXT,
  embedding  VECTOR(768) NOT NULL,
  VECTOR INDEX (embedding) M=8 DISTANCE=cosine
) ENGINE=InnoDB;

768 correspond à la largeur de sortie de plusieurs modèles d’embedding de phrases à poids ouverts largement utilisés ; fixez cette valeur en fonction de ce que produit votre modèle. Deux contraintes méritent d’être relevées dans ce DDL. La colonne indexée doit être NOT NULL, et M accepte des valeurs de 3 à 200, les valeurs élevées améliorant la précision au prix de la taille de l’index et de la vitesse d’écriture, d’après la référence create-table-with-vectors. La page du projet indique également une limite d’un seul index vectoriel par table.

Le serveur stocke et interroge les vecteurs ; il ne les produit pas. Le tableau provient donc de votre modèle d’embedding et est inséré sous forme de texte :

INSERT INTO support_articles (id, tenant_id, body, embedding)
VALUES (1, 17, 'Resetting a device token',
        VEC_FromText('[0.021, -0.113, 0.447, ...]'));

Comme les embeddings résident dans une table InnoDB ordinaire, une clause WHERE et un classement par similarité s’exécutent au sein d’une seule instruction transactionnelle. Un service vectoriel greffé à côté de la base de données ne peut pas rivaliser : restreindre une recherche des plus proches voisins aux lignes d’un seul tenant ne nécessite ni jointure entre deux systèmes ni post-filtrage de résultats que vous avez déjà payé pour récupérer.

SELECT id, body
FROM support_articles
WHERE tenant_id = 17
ORDER BY VEC_DISTANCE_COSINE(embedding, VEC_FromText('[...]'))
LIMIT 10;

Pourquoi l’index vectoriel est-il ignoré ?

L’index n’entre en jeu que lorsque la requête trie sur un simple appel de fonction de distance, en utilisant la métrique pour laquelle l’index a été construit, et limite le nombre de lignes avec un LIMIT. Interrogez un index construit en cosinus avec la fonction euclidienne, et la documentation de référence est explicite : l’index ne peut pas servir la requête, qui dégénère alors en parcours complet de la table :

-- index above was built with DISTANCE=cosine
SELECT id, body
FROM support_articles
WHERE tenant_id = 17
ORDER BY VEC_DISTANCE_EUCLIDEAN(embedding, VEC_FromText('[...]'))
LIMIT 10;

La fonction générique VEC_DISTANCE évite ce piège en se résolvant en distance euclidienne ou cosinus selon l’index sous-jacent, comme le décrit la présentation des vecteurs ; ces deux métriques sont les seules prises en charge. Si le rappel (recall) avec de petites valeurs de LIMIT est important, mhnsw_ef_search définit le nombre de candidats que la recherche dans l’index conserve en lice : 20 par défaut, réglable de 1 à 10000. La recherche n’en examine jamais moins, même lorsque LIMIT en demande moins ; augmenter cette valeur améliore donc la qualité au prix du temps de recherche.

À titre de comparaison, MySQL 8.0 n’a pas de type VECTOR ; un type vectoriel est apparu dans la série 9.x, et la recherche vectorielle appuyée sur un index est documentée comme une capacité HeatWave, où HeatWave GenAI construit lui-même les index pour les colonnes vectorielles fréquemment interrogées. Dans PostgreSQL, ce rôle revient à pgvector, une extension à installer et activer.

Tables versionnées par le système : comment interroger l’état de mardi dernier ?

Une table versionnée par le système conserve chaque version remplacée de chaque ligne au sein même de la table, si bien qu’une lecture à un instant donné se réduit à une clause sur un SELECT ordinaire, plutôt qu’à un trigger d’audit écrivant dans une table d’historique que vous devez maintenir. Comme les anciennes versions cohabitent avec les versions courantes, vous pouvez lire la table telle qu’elle était à n’importe quel moment passé, retracer ce qui a changé et comparer deux dates côte à côte.

CREATE TABLE subscription (
  account_id  BIGINT PRIMARY KEY,
  plan        VARCHAR(32),
  seats       INT
) WITH SYSTEM VERSIONING;

SELECT account_id, plan, seats
FROM subscription
FOR SYSTEM_TIME AS OF TIMESTAMP '2025-11-04 09:00:00'
WHERE account_id = 4021;

C’est tout ce qu’il y a à savoir. L’historique n’est renvoyé que si FOR SYSTEM_TIME est spécifié, et la référence sur les tables versionnées par le système documente AS OF, BETWEEN, FROM ... TO et ALL comme formes de requête. La forme DDL explicite déclare des colonnes GENERATED ALWAYS AS ROW START et ROW END avec un PERIOD FOR SYSTEM_TIME ; la forme abrégée ci-dessus stocke la même information derrière les pseudo-colonnes ROW_START et ROW_END. Sur InnoDB, vous pouvez aussi versionner par transaction à l’aide de colonnes row-start et row-end de type BIGINT UNSIGNED et lire avec FOR SYSTEM_TIME AS OF TRANSACTION. La documentation des différences de MariaDB elle-même range les tables de données temporelles parmi les capacités auxquelles MySQL n’offre aucun équivalent.

Périodes de temps applicatif pour la validité métier

Le versionnement système enregistre le moment où l’information a été communiquée à la base ; une période de temps applicatif enregistre le moment où le fait était réellement vrai. Une période de temps applicatif est un intervalle délimité par deux colonnes temporelles de type et de largeur identiques, et elle versionne vos données au niveau applicatif plutôt qu’au niveau serveur. Un prix assorti d’une fenêtre de validité en est le cas d’école.

CREATE TABLE price_list (
  sku        VARCHAR(32),
  price      DECIMAL(10,2),
  valid_from DATE,
  valid_to   DATE,
  PERIOD FOR validity(valid_from, valid_to),
  UNIQUE (sku, validity WITHOUT OVERLAPS)
);

UPDATE price_list FOR PORTION OF validity
  FROM '2026-01-01' TO '2026-04-01'
  SET price = 18.00
WHERE sku = 'KB-114';

Déclarer une période impose NOT NULL aux deux colonnes et ajoute discrètement une contrainte vérifiant que la première valeur précède la seconde. WITHOUT OVERLAPS sur une clé primaire ou unique rejette ensuite les lignes dont les périodes se chevauchent. Cette clause est documentée depuis MariaDB 10.5.3 ; les périodes elles-mêmes, FOR PORTION compris, sont arrivées plus tôt, dans MariaDB 10.4.3. Déclarez à la fois une période et le versionnement système sur une même table et vous obtenez une table bitemporelle, qui applique les deux types de versionnement aux mêmes lignes simultanément. C’est ce qui permet de distinguer un prix qui était erroné mardi d’un prix simplement saisi en retard.

Peut-on choisir un moteur de stockage table par table ?

MariaDB définit le moteur de stockage au niveau de chaque table : les tables transactionnelles restent sur InnoDB tandis que d’autres tables du même schéma utilisent autre chose. Au-delà de la panoplie standard, la documentation des différences cite ColumnStore pour le traitement analytique distribué, MyRocks, le moteur S3 pour l’archivage cloud, Aria en remplacement de MyISAM, ainsi que CONNECT, SEQUENCE, Spider, SphinxSE, FederatedX et OQGRAPH.

CREATE TABLE event_archive (
  id   BIGINT PRIMARY KEY,
  body TEXT
) ENGINE=Aria;

Plusieurs d’entre eux sont livrés sous forme de paquets de plugins distincts plutôt que compilés dans le serveur ; consultez donc la documentation propre au moteur pour la version que vous installez avant de supposer qu’une simple clause ENGINE= suffira.

utf8mb4 par défaut et collations plus récentes

MariaDB a fait passer le jeu de caractères par défaut du serveur de latin1 à utf8mb4 en 11.6, et a mis à jour les collations vers UCA 14.0.0 au passage. Si vous effectuez une montée de version entre releases à support long terme, c’est en 11.8 que les deux changements atterrissent, et l’annonce de la version 11.8 LTS du 8 juin 2025 les présente comme faisant partie de cette release. Il s’agit ici de MariaDB qui retire l’un de ses propres réglages par défaut, antérieur aux emojis, et non d’un point sur lequel il dépasserait MySQL en matière de valeur par défaut. C’est le volet collations qui survit à la montée de version : l’ordre de tri et les comparaisons suivent un algorithme de collation Unicode plus récent que celui de MySQL ; recouper les résultats de tri vaut donc la peine si vous comparez les sorties des deux systèmes.

Les fonctionnalités MariaDB et les versions qui les ont introduites

FonctionnalitéCe que vous pouvez faireDisponibilité dans MariaDB
Recherche vectorielleStocker des embeddings dans VECTOR(N), indexer avec VECTOR INDEX, filtrer et classer en une seule instructionType VECTOR ajouté en 11.7.1, GA en 11.8 LTS, présent en 12.3 LTS
Tables versionnées par le systèmeLire une table telle qu’elle était à un horodatage ou une transaction passésDisponible dans les versions 11.8 et 12.3 LTS
Périodes de temps applicatifModéliser des fenêtres de validité métier et mettre à jour une tranche de l’une d’ellesPériodes et FOR PORTION depuis 10.4.3, WITHOUT OVERLAPS depuis 10.5.3, présents dans les LTS actuelles
Tables bitemporellesVersionner à la fois par temps système et par temps métier sur une même tablePrésentes dans les LTS actuelles
utf8mb4 par défaut, UCA 14.0.0Unicode sans modification de la configuration serveurPar défaut depuis 11.6, première LTS concernée : 11.8

Une note de migration à garder en tête : l’annonce de la version 11.8 indique que l’extension de la plage TIMESTAMP n’a nécessité aucune conversion de données à condition que les tables versionnées par le système ne soient pas utilisées, et désigne ces tables comme la seule complication connue, la représentation interne des timestamps ayant changé.

Choisissez parmi ces cinq fonctionnalités celle qui répond à un problème que vous rencontrez déjà. S’il s’agit de l’historique d’audit, créez une table jetable WITH SYSTEM VERSIONING, modifiez une ligne deux fois, puis relisez-la avec FOR SYSTEM_TIME AS OF ; vous saurez en quelques minutes si cela remplace le trigger que vous maintenez depuis des mois.

FAQ

Puis-je activer le versionnement système sur une table déjà existante ?

Oui. ALTER TABLE t ADD SYSTEM VERSIONING l'active sur une table existante, et ALTER TABLE t DROP SYSTEM VERSIONING le retire, ce qui supprime tout l'historique. Les deux opérations reconstruisent la table et peuvent donc être lentes sur de grandes tables. Les modifications de schéma ultérieures dépendent du paramètre system_versioning_alter_history : avec ERROR, l'altération d'une table versionnée échoue ; avec KEEP, l'altération réussit mais les requêtes historiques affichent la nouvelle structure de table.

Comment empêcher une table versionnée par le système de croître indéfiniment ?

Trois options sont documentées : purger avec l'instruction DELETE HISTORY, qui exige le privilège DELETE HISTORY ; partitionner par SYSTEM_TIME et supprimer les partitions historiques, sachant que vous ne pouvez supprimer ni la partition courante ni l'unique partition historique ; ou retirer puis réactiver le versionnement système, ce qui efface l'historique au prix d'une reconstruction de la table. TRUNCATE TABLE ne fera pas l'affaire non plus : le serveur le refuse avec l'erreur 4137 afin que l'historique soit préservé.

Puis-je indexer une même colonne vectorielle à la fois pour la distance cosinus et la distance euclidienne dans MariaDB ?

Non. Un index vectoriel est construit pour une seule fonction de distance, cosinus et euclidienne (la valeur par défaut) étant les valeurs admises, et une recherche utilisant une autre fonction de distance ne peut pas exploiter cet index. MariaDB n'autorise par ailleurs qu'un seul index vectoriel par table : desservir une seconde métrique implique donc de supprimer l'index et de le reconstruire avec une autre valeur de DISTANCE, plutôt que d'en ajouter un second à côté.

Le passage à utf8mb4 par défaut dans MariaDB 11.8 affecte-t-il la réplication vers des serveurs plus anciens ?

Oui. Le jeu de caractères par défaut est passé de latin1 à utf8mb4 et la collation par défaut à utf8mb4_uca1400_ai_ci dans MariaDB 11.6, et 11.8 est la première version à support long terme à intégrer ce changement. Les versions antérieures ne disposent pas de cette collation : un primaire MariaDB 11.8 ne peut donc pas répliquer vers un réplica MariaDB 10.6, sauf à reconfigurer le serveur sur les anciennes valeurs par défaut.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.