5 Recursos do MariaDB Que Vale a Pena Conhecer
Recursos importantes do MariaDB: busca vetorial, tabelas com versionamento do sistema e application-time, engine por tabela e utf8mb4 padrão no 11.8 LTS.
Os cinco recursos mais relevantes do MariaDB para uma equipe que opera MySQL 8.0 são: busca vetorial nativa, tabelas versionadas pelo sistema (system-versioned tables), períodos de tempo de aplicação (application-time periods), escolha de storage engine por tabela e utf8mb4 como padrão do servidor com collations UCA 14.0.0, em vigor desde o MariaDB 11.6 e mantidos pela linha 11.8 LTS.
Se você está avaliando uma decisão de versão em um parque de MySQL 8.0, o MariaDB é uma das opções que vale a pena colocar na lista.
O que segue aborda cada recurso individualmente: o que ele faz e o SQL que você digitaria. As referências de versão apontam para o MariaDB 11.8 LTS e o MariaDB 12.3 LTS, a release que a maioria das equipes começando agora instalaria.
Principais Pontos
- O MariaDB entrega busca por similaridade vetorial dentro do servidor community: uma coluna
VECTOR(N)e umVECTOR INDEXconstruído sobre um algoritmo HNSW modificado, sem nenhuma extensão para instalar. - O MariaDB usa o índice vetorial apenas quando o
ORDER BYé uma chamada de distância pura correspondente à métrica com a qual o índice foi construído, seguida de umLIMIT; uma função de distância incompatível resulta em fallback para um full table scan. WITH SYSTEM VERSIONINGsomado aSELECT ... FOR SYSTEM_TIME AS OFfornece consultas point-in-time sem triggers de auditoria ou uma tabela de histórico paralela.PERIOD FORdeclara a validade de negócio em uma tabela, e declarar tanto o versionamento de sistema quanto um período de tempo de aplicação torna a tabela bitemporal.- O conjunto de caracteres padrão é utf8mb4 desde o MariaDB 11.6, com collations em UCA 14.0.0, e a 11.8 é a primeira release de suporte de longo prazo a trazê-lo.
Como o MariaDB Faz Busca Vetorial Sem Extensão?
O MariaDB armazena e pesquisa embeddings no próprio servidor community: uma coluna VECTOR(N), um VECTOR INDEX usando um algoritmo HNSW modificado e funções de distância para similaridade cosine e euclidean. A página do projeto MariaDB Vector posiciona a disponibilidade geral na 11.8 LTS, e a referência do tipo VECTOR limita uma coluna a 16.383 dimensões. Nada adicional é instalado, e não há um segundo datastore ao lado das suas linhas esperando para sair de sincronia com elas.
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 corresponde à largura de saída de vários modelos de embedding de sentenças de pesos abertos amplamente utilizados; defina o valor conforme o que seu modelo emitir. Duas restrições merecem ser extraídas desse DDL. A coluna indexada precisa ser NOT NULL, e M aceita valores de 3 a 200, com valores mais altos comprando acurácia ao custo de tamanho de índice e velocidade de escrita, conforme a referência create-table-with-vectors. A página do projeto também informa um limite de um índice vetorial por tabela.
O servidor armazena e pesquisa vetores; ele não os produz. Portanto o array vem do seu modelo de embedding e 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 os embeddings vivem em uma tabela InnoDB comum, uma cláusula WHERE e um ranking de similaridade são executados como uma única instrução transacional. Um serviço vetorial acoplado ao lado do banco de dados não consegue igualar isso: restringir uma busca de vizinhos mais próximos às linhas de um único tenant não exige join entre dois sistemas nem pós-filtragem de resultados que você já pagou para recuperar.
SELECT id, body
FROM support_articles
WHERE tenant_id = 17
ORDER BY VEC_DISTANCE_COSINE(embedding, VEC_FromText('[...]'))
LIMIT 10;
Por Que o Índice Vetorial É Ignorado?
O índice só entra em ação quando a consulta ordena por uma chamada de distância pura, usando a métrica para a qual o índice foi construído, e limita as linhas com um LIMIT. Consulte um índice construído com cosine usando a função euclidean e a documentação de referência é explícita: o índice não pode atender à consulta, e ela degrada para um full table scan:
-- 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;
A função genérica VEC_DISTANCE evita a armadilha resolvendo para euclidean ou cosine de acordo com o índice subjacente, como descrito na visão geral de vetores; essas duas métricas são as únicas suportadas. Se o recall com valores pequenos de LIMIT importar, mhnsw_ef_search define quantos candidatos a resultado a busca no índice mantém em jogo: 20 por padrão, configurável de 1 a 10000. A busca nunca procura menos do que isso, mesmo quando o LIMIT pede menos, de modo que aumentá-lo compra qualidade ao custo de tempo de busca.
Para comparação, o MySQL 8.0 não tem tipo VECTOR; um tipo vetorial chegou na série 9.x, e a busca vetorial apoiada em índice é documentada como uma capacidade do HeatWave, onde o HeatWave GenAI constrói os índices por conta própria para colunas vetoriais consultadas com frequência. No PostgreSQL, o mesmo trabalho fica a cargo do pgvector, uma extensão que você instala e habilita.
Tabelas Versionadas pelo Sistema: Como Consultar a Terça-Feira Passada?
Uma tabela versionada pelo sistema mantém toda versão substituída de cada linha dentro da própria tabela, de modo que uma leitura point-in-time é uma cláusula em um SELECT normal, em vez de uma trigger de auditoria gravando em uma tabela de histórico que você precisa manter. Como as versões antigas permanecem junto às vigentes, você pode ler a tabela como ela estava em qualquer momento passado, rastrear o que mudou e colocar duas datas lado a lado.
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;
Esse é o recurso inteiro. O histórico é retornado quando FOR SYSTEM_TIME é especificado, e a referência de tabelas versionadas pelo sistema documenta AS OF, BETWEEN, FROM ... TO e ALL como as formas de consulta. A forma DDL explícita declara colunas GENERATED ALWAYS AS ROW START e ROW END com um PERIOD FOR SYSTEM_TIME; a forma curta acima armazena a mesma informação por trás das pseudocolunas ROW_START e ROW_END. No InnoDB você também pode versionar por transação usando colunas row-start e row-end do tipo BIGINT UNSIGNED e ler com FOR SYSTEM_TIME AS OF TRANSACTION. A própria documentação de diferenças do MariaDB lista tabelas de dados temporais entre as capacidades para as quais o MySQL não tem equivalente.
Períodos de Tempo de Aplicação para Validade de Negócio
O versionamento de sistema registra quando o banco de dados foi informado de algo; um período de tempo de aplicação registra quando o fato foi de fato verdadeiro. Um período de tempo de aplicação é um intervalo delimitado por duas colunas temporais de tipo e largura correspondentes, e versiona seus dados no nível da aplicação em vez do nível do servidor. Um preço com uma janela de validade é o 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 um período força ambas as colunas a NOT NULL e adiciona silenciosamente uma verificação de que o primeiro valor é anterior ao segundo. WITHOUT OVERLAPS em uma chave primária ou única então rejeita linhas cujos períodos colidam. Essa cláusula está documentada a partir do MariaDB 10.5.3; os períodos em si, incluindo FOR PORTION, chegaram antes, no MariaDB 10.4.3. Declare tanto um período quanto versionamento de sistema em uma mesma tabela e você obtém uma tabela bitemporal, que executa os dois tipos de versionamento nas mesmas linhas ao mesmo tempo. É isso que separa um preço que estava errado na terça-feira de um que foi apenas inserido com atraso.
É Possível Escolher um Storage Engine por Tabela?
O MariaDB define o storage engine por tabela, de modo que tabelas transacionais permanecem no InnoDB enquanto outras tabelas no mesmo schema usam algo diferente. Além do conjunto padrão, a documentação de diferenças cita o ColumnStore para processamento analítico distribuído, o MyRocks, o engine S3 para arquivamento em nuvem, o Aria como substituto do MyISAM, além de CONNECT, SEQUENCE, Spider, SphinxSE, FederatedX e OQGRAPH.
CREATE TABLE event_archive (
id BIGINT PRIMARY KEY,
body TEXT
) ENGINE=Aria;
Vários deles são distribuídos como pacotes de plugin separados, em vez de serem compilados dentro do servidor, portanto consulte a documentação do próprio engine para a release que você está instalando antes de supor que uma simples cláusula ENGINE= é suficiente.
Padrões utf8mb4 e Collations Mais Recentes
O MariaDB mudou o conjunto de caracteres padrão do servidor de latin1 para utf8mb4 na 11.6, e atualizou as collations para UCA 14.0.0 no mesmo movimento. Se você atualiza entre releases de suporte de longo prazo, a 11.8 é onde ambos chegam, e o anúncio de lançamento da 11.8 LTS, de 8 de junho de 2025, os apresenta como parte dessa release. Trata-se do MariaDB aposentando um padrão próprio anterior aos emojis, não de um ponto em que ele ultrapassa o MySQL no padrão em si. O lado das collations é a parte que sobrevive à atualização: ordem de classificação e comparação seguem um algoritmo de collation Unicode mais novo que o do MySQL, então vale conferir resultados de ordenação cruzadamente se você comparar a saída entre os dois.
Recursos do MariaDB e as Releases em Que Chegaram
| Recurso | O que você pode fazer | Disponibilidade no MariaDB |
|---|---|---|
| Busca vetorial | Armazenar embeddings em VECTOR(N), indexar com VECTOR INDEX, filtrar e ranquear em uma única instrução | Tipo VECTOR adicionado na 11.7.1, GA na 11.8 LTS, presente na 12.3 LTS |
| Tabelas versionadas pelo sistema | Ler uma tabela como ela estava em um timestamp ou transação passada | Disponível nas releases 11.8 e 12.3 LTS |
| Períodos de tempo de aplicação | Modelar janelas de validade de negócio e atualizar uma fatia de uma delas | Períodos e FOR PORTION a partir da 10.4.3, WITHOUT OVERLAPS a partir da 10.5.3, presentes nas LTS atuais |
| Tabelas bitemporais | Versionar tanto por tempo de sistema quanto por tempo de negócio em uma mesma tabela | Presente nas LTS atuais |
| utf8mb4 padrão, UCA 14.0.0 | Unicode sem alteração de configuração do servidor | Padrão a partir da 11.6, a primeira LTS com ele é a 11.8 |
Uma observação de atualização que vale levar: o post de lançamento da 11.8 registra que a extensão do intervalo de TIMESTAMP não exigiu conversão de dados desde que tabelas versionadas pelo sistema não estejam em uso, e aponta essas tabelas como a única complicação conhecida, porque a representação interna de timestamp mudou.
Escolha, entre esses cinco, aquele que corresponde a um problema que você já tem. Se for histórico de auditoria, crie uma tabela descartável WITH SYSTEM VERSIONING, altere uma linha duas vezes e leia-a de volta com FOR SYSTEM_TIME AS OF; em poucos minutos você saberá se isso substitui a trigger que você vem mantendo.
Perguntas Frequentes
Posso ativar o versionamento de sistema para uma tabela que já existe?
Sim. ALTER TABLE t ADD SYSTEM VERSIONING habilita o recurso em uma tabela existente, e ALTER TABLE t DROP SYSTEM VERSIONING o remove, o que apaga todo o histórico. Ambos reconstroem a tabela, portanto podem ser lentos em tabelas grandes. Mudanças de schema posteriores dependem da configuração system_versioning_alter_history: com ERROR, alterar uma tabela versionada falha; com KEEP, o alter é bem-sucedido, mas as consultas históricas exibem a nova estrutura da tabela.
Como evitar que uma tabela versionada pelo sistema cresça indefinidamente?
Existem três opções documentadas: podar com a instrução DELETE HISTORY, que exige o privilégio DELETE HISTORY; particionar por SYSTEM_TIME e descartar partições históricas, observando que não é possível descartar a partição atual nem a única partição histórica; ou remover e readicionar o versionamento de sistema, o que limpa o histórico ao custo de uma reconstrução da tabela. TRUNCATE TABLE também não resolve: o servidor o recusa com o erro 4137 para que o histórico sobreviva.
Posso indexar uma coluna vetorial para distância cosine e euclidean ao mesmo tempo no MariaDB?
Não. Um índice vetorial é construído para uma única função de distância, tendo cosine e euclidean (o padrão) como valores válidos, e uma busca usando uma função de distância diferente não pode usar esse índice. O MariaDB também permite apenas um índice vetorial por tabela, portanto atender a uma segunda métrica significa descartar o índice e reconstruí-lo com um valor de DISTANCE diferente, em vez de adicionar outro ao lado dele.
O padrão utf8mb4 no MariaDB 11.8 afeta a replicação para servidores mais antigos?
Sim. O conjunto de caracteres padrão mudou de latin1 para utf8mb4 e a collation padrão para utf8mb4_uca1400_ai_ci no MariaDB 11.6, e a 11.8 é a primeira release de suporte de longo prazo a trazer a mudança. Releases mais antigas não possuem essa collation, portanto um primary MariaDB 11.8 não consegue replicar para uma réplica MariaDB 10.6 a menos que você aponte o servidor de volta para os padrões antigos.