5 características de MariaDB que vale la pena conocer
Funciones de MariaDB que conviene conocer: búsqueda vectorial, tablas con versionado del sistema, períodos de aplicación, motores por tabla y utf8mb4 en 11.8 LTS.
Las cinco características más relevantes de MariaDB para un equipo que opera MySQL 8.0 son la búsqueda vectorial integrada, las tablas con versionado de sistema (system-versioned tables), los períodos de tiempo de aplicación (application-time periods), la elección del motor de almacenamiento por tabla y el valor predeterminado utf8mb4 en el servidor con colaciones UCA 14.0.0, disponibles desde MariaDB 11.6 y mantenidas en la línea 11.8 LTS.
Si estás evaluando una decisión de versión sobre un parque de servidores MySQL 8.0, MariaDB es una de las opciones que conviene incluir en la lista.
Lo que sigue aborda cada característica por turno: qué hace y el SQL que escribirías. Las referencias de versión apuntan a MariaDB 11.8 LTS y MariaDB 12.3 LTS, la release que la mayoría de los equipos que empiezan ahora instalarían.
Puntos clave
- MariaDB incorpora la búsqueda por similitud vectorial dentro del servidor community: una columna
VECTOR(N)y unVECTOR INDEXconstruido sobre un algoritmo HNSW modificado, sin ninguna extensión que instalar. - MariaDB usa el índice vectorial únicamente cuando el
ORDER BYes una llamada de distancia sin más que coincide con la métrica con la que se construyó el índice, seguida de unLIMIT; una función de distancia que no coincida provoca un fallback a un escaneo completo de la tabla. WITH SYSTEM VERSIONINGjunto conSELECT ... FOR SYSTEM_TIME AS OFte da consultas a un punto en el tiempo sin triggers de auditoría ni una tabla de historial paralela.PERIOD FORdeclara la validez de negocio sobre una tabla, y declarar tanto el versionado de sistema como un período de tiempo de aplicación convierte la tabla en bitemporal.- El juego de caracteres predeterminado es utf8mb4 desde MariaDB 11.6, con colaciones basadas en UCA 14.0.0, y 11.8 es la primera release de soporte a largo plazo que lo incorpora.
¿Cómo hace MariaDB búsqueda vectorial sin una extensión?
MariaDB almacena y busca embeddings en el propio servidor community: una columna VECTOR(N), un VECTOR INDEX que usa un algoritmo HNSW modificado y funciones de distancia para similitud coseno y euclidiana. La página del proyecto MariaDB Vector sitúa la disponibilidad general en 11.8 LTS, y la referencia del tipo VECTOR limita una columna a 16.383 dimensiones. No se instala nada adicional, y no hay un segundo almacén de datos junto a tus filas esperando a desincronizarse de ellas.
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 coincide con el ancho de salida de varios modelos de embeddings de oraciones de pesos abiertos ampliamente usados; ajústalo a lo que emita tu modelo. Hay dos restricciones que conviene leer en ese DDL. La columna indexada debe ser NOT NULL, y M acepta valores de 3 a 200, donde valores más altos compran precisión a costa del tamaño del índice y la velocidad de escritura, según la referencia de create-table-with-vectors. La página del proyecto también indica un límite de un índice vectorial por tabla.
El servidor guarda y busca vectores; no los produce. Así que el array proviene de tu modelo de embeddings y entra como texto:
INSERT INTO support_articles (id, tenant_id, body, embedding)
VALUES (1, 17, 'Resetting a device token',
VEC_FromText('[0.021, -0.113, 0.447, ...]'));
Como los embeddings viven en una tabla InnoDB corriente, una cláusula WHERE y una clasificación por similitud se ejecutan como una única sentencia transaccional. Un servicio vectorial acoplado al lado de la base de datos no puede igualar eso: acotar una búsqueda de vecinos más cercanos a las filas de un solo tenant no requiere un join entre dos sistemas ni un post-filtrado de resultados que ya pagaste por recuperar.
SELECT id, body
FROM support_articles
WHERE tenant_id = 17
ORDER BY VEC_DISTANCE_COSINE(embedding, VEC_FromText('[...]'))
LIMIT 10;
¿Por qué se omite el índice vectorial?
El índice solo entra en juego cuando la consulta ordena por una llamada de distancia simple, usando la métrica para la que se construyó el índice, y acota las filas con un LIMIT. Si consultas un índice construido con coseno usando la función euclidiana, la documentación de referencia es explícita: el índice no puede atender la consulta y esta degrada a un escaneo completo de la tabla:
-- 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 función genérica VEC_DISTANCE evita la trampa al resolverse a euclidiana o coseno según el índice subyacente, tal como se describe en la visión general de vectores; esas dos métricas son las únicas soportadas. Si el recall con valores pequeños de LIMIT importa, mhnsw_ef_search define cuántos candidatos de resultado mantiene en juego la búsqueda del índice: 20 por defecto, configurable de 1 a 10000. La búsqueda nunca busca menos que eso, incluso cuando el LIMIT pide menos, así que subirlo compra calidad a costa de tiempo de búsqueda.
A modo de comparación, MySQL 8.0 no tiene tipo VECTOR; un tipo vectorial llegó en la serie 9.x, y la búsqueda vectorial respaldada por índices está documentada como una capacidad de HeatWave, donde HeatWave GenAI construye los índices por sí mismo para las columnas vectoriales que se consultan con frecuencia. En PostgreSQL el mismo trabajo recae en pgvector, una extensión que instalas y habilitas.
Tablas con versionado de sistema: ¿cómo consultas el martes pasado?
Una tabla con versionado de sistema conserva dentro de la propia tabla cada versión reemplazada de cada fila, de modo que una lectura a un punto en el tiempo es una cláusula sobre un SELECT normal en lugar de un trigger de auditoría escribiendo en una tabla de historial que tienes que mantener. Como las versiones antiguas permanecen junto a las vigentes, puedes leer la tabla tal como estaba en cualquier momento pasado, rastrear qué cambió y poner dos fechas una al lado de la otra.
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;
Eso es toda la característica. El historial se devuelve cuando se especifica FOR SYSTEM_TIME, y la referencia de tablas con versionado de sistema documenta AS OF, BETWEEN, FROM ... TO y ALL como formas de consulta. La forma DDL explícita declara columnas GENERATED ALWAYS AS ROW START y ROW END con un PERIOD FOR SYSTEM_TIME; la forma corta de arriba almacena la misma información detrás de las pseudo-columnas ROW_START y ROW_END. En InnoDB también puedes versionar por transacción usando columnas de inicio y fin de fila BIGINT UNSIGNED y leer con FOR SYSTEM_TIME AS OF TRANSACTION. La propia documentación de diferencias de MariaDB enumera las tablas de datos temporales entre las capacidades para las que MySQL no tiene equivalente.
Períodos de tiempo de aplicación para la validez de negocio
El versionado de sistema registra cuándo se le comunicó algo a la base de datos; un período de tiempo de aplicación registra cuándo el hecho fue realmente cierto. Un período de tiempo de aplicación es un intervalo delimitado por dos columnas temporales del mismo tipo y ancho, y versiona tus datos a nivel de aplicación en lugar de a nivel de servidor. Un precio con una ventana de validez es el caso canónico.
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';
Declarar un período fuerza ambas columnas a NOT NULL y añade de forma silenciosa una verificación de que el primer valor sea anterior al segundo. WITHOUT OVERLAPS en una clave primaria o única rechaza entonces las filas cuyos períodos colisionan. Esa cláusula está documentada desde MariaDB 10.5.3; los períodos en sí, incluido FOR PORTION, llegaron antes, en MariaDB 10.4.3. Declara tanto un período como versionado de sistema en una misma tabla y obtienes una tabla bitemporal, que ejecuta ambos tipos de versionado sobre las mismas filas a la vez. Eso es lo que separa un precio que estaba mal el martes de uno que simplemente se introdujo tarde.
¿Puedes elegir un motor de almacenamiento por tabla?
MariaDB establece el motor de almacenamiento por tabla, de modo que las tablas transaccionales permanecen en InnoDB mientras otras tablas del mismo esquema usan algo distinto. Más allá del conjunto estándar, la documentación de diferencias menciona ColumnStore para procesamiento analítico distribuido, MyRocks, el motor S3 para archivado en la nube, Aria como sustituto de MyISAM, además de CONNECT, SEQUENCE, Spider, SphinxSE, FederatedX y OQGRAPH.
CREATE TABLE event_archive (
id BIGINT PRIMARY KEY,
body TEXT
) ENGINE=Aria;
Varios de estos se distribuyen como paquetes de plugin independientes en lugar de estar compilados dentro del servidor, así que consulta la documentación propia del motor para la release que vas a instalar antes de dar por sentado que basta con una cláusula ENGINE=.
Valores predeterminados utf8mb4 y colaciones más recientes
MariaDB cambió el juego de caracteres predeterminado del servidor de latin1 a utf8mb4 en la 11.6, y por el camino actualizó las colaciones a UCA 14.0.0. Si actualizas entre releases de soporte a largo plazo, 11.8 es donde aterrizan ambos, y el anuncio de la release 11.8 LTS del 8 de junio de 2025 los presenta como parte de esa release. Esto es MariaDB retirando un valor predeterminado propio que es anterior a los emoji, no un punto en el que adelante a MySQL en el propio valor predeterminado. El lado de las colaciones es la parte que sobrevive a la actualización: el orden de clasificación y la comparación siguen un algoritmo de colación Unicode más reciente que el de MySQL, así que vale la pena contrastar los resultados de ordenación si comparas la salida entre ambos.
Características de MariaDB y las releases en las que aterrizaron
| Característica | Qué puedes hacer | Disponibilidad en MariaDB |
|---|---|---|
| Búsqueda vectorial | Almacenar embeddings en VECTOR(N), indexar con VECTOR INDEX, filtrar y clasificar en una sola sentencia | Tipo VECTOR añadido en 11.7.1, GA en 11.8 LTS, presente en 12.3 LTS |
| Tablas con versionado de sistema | Leer una tabla tal como estaba en un timestamp o transacción pasados | Disponible en las releases 11.8 y 12.3 LTS |
| Períodos de tiempo de aplicación | Modelar ventanas de validez de negocio y actualizar un tramo de una de ellas | Períodos y FOR PORTION desde 10.4.3, WITHOUT OVERLAPS desde 10.5.3, presentes en la LTS actual |
| Tablas bitemporales | Versionar por tiempo de sistema y tiempo de negocio en una misma tabla | Presentes en la LTS actual |
| utf8mb4 por defecto, UCA 14.0.0 | Unicode sin cambiar la configuración del servidor | Predeterminado desde 11.6, la primera LTS con ello es 11.8 |
Una nota de actualización que conviene tener presente: la publicación de la release 11.8 deja constancia de que la extensión del rango de TIMESTAMP no necesitó conversión de datos siempre que no se usen tablas con versionado de sistema, y señala esas tablas como la única complicación conocida, porque la representación interna del timestamp cambió.
Elige de estas cinco la que corresponda a un problema que ya tienes. Si se trata del historial de auditoría, crea una tabla desechable WITH SYSTEM VERSIONING, cambia una fila dos veces y vuelve a leerla con FOR SYSTEM_TIME AS OF; en cuestión de minutos sabrás si reemplaza el trigger que has estado manteniendo.
Preguntas frecuentes
¿Puedo activar el versionado de sistema para una tabla que ya existe?
Sí. ALTER TABLE t ADD SYSTEM VERSIONING lo habilita en una tabla existente, y ALTER TABLE t DROP SYSTEM VERSIONING lo elimina, lo que borra todo el historial. Ambas reconstruyen la tabla, así que pueden ser lentas en tablas grandes. Los cambios de esquema posteriores dependen de la configuración system_versioning_alter_history: con ERROR, alterar una tabla versionada falla; con KEEP, la alteración tiene éxito pero las consultas históricas muestran la nueva estructura de la tabla.
¿Cómo evito que una tabla con versionado de sistema crezca indefinidamente?
Existen tres opciones documentadas: podar con la sentencia DELETE HISTORY, que requiere el privilegio DELETE HISTORY; particionar por SYSTEM_TIME y eliminar particiones históricas, teniendo en cuenta que no puedes eliminar la partición actual ni la única histórica; o eliminar y volver a añadir el versionado de sistema, lo que limpia el historial a costa de una reconstrucción de la tabla. TRUNCATE TABLE tampoco sirve: el servidor lo rechaza con el error 4137 para que el historial sobreviva.
¿Puedo indexar una misma columna vectorial tanto para distancia coseno como euclidiana en MariaDB?
No. Un índice vectorial se construye para una única función de distancia, siendo coseno y euclidiana (la predeterminada) los valores válidos, y una búsqueda que use una función de distancia diferente no puede usar ese índice. MariaDB además permite solo un índice vectorial por tabla, así que atender una segunda métrica implica eliminar el índice y reconstruirlo con un valor DISTANCE distinto, en lugar de añadir otro junto a él.
¿El valor predeterminado utf8mb4 en MariaDB 11.8 afecta a la replicación hacia servidores más antiguos?
Sí. El juego de caracteres predeterminado cambió de latin1 a utf8mb4 y la colación predeterminada a utf8mb4_uca1400_ai_ci en MariaDB 11.6, y 11.8 es la primera release de soporte a largo plazo que incorpora el cambio. Las releases más antiguas no tienen esa colación, así que un primario MariaDB 11.8 no puede replicar hacia una réplica MariaDB 10.6 a menos que configures el servidor de vuelta a los valores predeterminados antiguos.