Todos os produtos
Search
Central de documentação

PolarDB:Introdução à arquitetura técnica do In-Memory Column Index

Última atualização: Jun 28, 2026

O In-Memory Column Index (IMCI) adiciona um column store e uma camada de computação em memória ao PolarDB for MySQL, permitindo o processamento híbrido transacional e analítico (HTAP) em um único cluster. Essa abordagem mantém o desempenho de OLTP e elimina a necessidade de migrar dados.

Por que o MySQL precisa de um column store

O MySQL foi projetado para processamento de transações online (OLTP): consultas a linhas individuais, gravações simultâneas e transações de baixa latência. Como os clusters do PolarDB armazenam rotineiramente centenas de terabytes, os usuários precisam cada vez mais de análises em tempo real sobre os mesmos dados que alimentam suas aplicações. Três abordagens arquitetônicas surgiram para atender a essa demanda.

MySQL + banco de dados AP dedicado

Implante dois sistemas separados — o MySQL para OLTP e um banco de dados OLAP especializado para análises — com um pipeline de sincronização entre eles. Embora essa estratégia ofereça o melhor mecanismo para cada carga de trabalho, o custo é alto: duas pilhas tecnológicas para manter, latência de sincronização que deixa os dados analíticos desatualizados e ausência de um caminho direto para consistência em tempo real.

image.png

Design divergente de múltiplas réplicas

Bancos de dados NewSQL distribuídos, como o TiDB (a partir da versão 4.0), atribuem formatos de armazenamento diferentes a réplicas distintas dentro de cada grupo Raft. Uma réplica executa o TiFlash, um column store, para atender a consultas analíticas; as outras réplicas cuidam do OLTP. O roteamento inteligente de consultas seleciona automaticamente a réplica adequada. Esse modelo funciona bem para novas implantações, mas exige a migração do MySQL, o que introduz problemas de compatibilidade.

image.png

Armazenamento híbrido linha-coluna integrado

A abordagem mais avançada armazena dados orientados a linhas e a colunas na mesma instância de banco de dados. Todos os principais bancos de dados comerciais utilizam esse design:

  • A Oracle introduziu o conjunto Database In-Memory no Oracle Database 12c (2013), utilizando um column store em memória com execução híbrida linha-coluna e otimizações de consulta baseadas em expressões materializadas e JoinGroup.

  • O SQL Server adicionou índices columnstore no SQL Server 2016 SP1, com suporte a tabelas orientadas a linhas, tabelas orientadas a colunas e combinações híbridas.

  • O IBM Db2 lançou o BLU Acceleration no Kepler 10.5 (2013), combinando column store, computação em memória e data skipping.

image.png

Os três convergiram para esse design pelo mesmo motivo: um column store oferece melhor eficiência de E/S (compressão, data skipping, column pruning) e melhor eficiência de CPU (padrões de acesso favoráveis ao cache). No entanto, os índices de column store são esparsos — eles não conseguem localizar linhas individuais com a mesma eficiência de um índice B+ tree. Um mecanismo híbrido linha-coluna resolve essa questão: o row store lida com o OLTP por meio de indexação precisa no nível da linha, enquanto o column store acelera varreduras analíticas em massa. A baixa latência da DRAM compensa a diferença de desempenho nas atualizações do column store.

Por que o PolarDB precisava de um novo mecanismo de execução

A pilha de capacidades do PolarDB espelha o MySQL open source. Embora o PolarDB lide eficientemente com o OLTP e suporte até 500 TB de dados por cluster, consultas analíticas complexas ainda são lentas. Os gargalos são intrínsecos à arquitetura do MySQL:

  • Modelo de execução serial. O modelo de iterador volcano do MySQL processa uma linha por vez. Cada recuperação de linha aciona várias camadas de chamadas de função, incluindo despacho de funções virtuais. Isso destrói a eficiência do pipeline da CPU e impede o uso de instruções SIMD.

  • Ausência de consulta paralela. O executor do MySQL é single-thread. O suporte a consultas paralelas no MySQL 8.0 abrange apenas operações básicas, como COUNT(*); SQL analítico complexo é executado em série, independentemente de quantos núcleos de CPU estejam disponíveis.

  • Desperdício de E/S no row store. Quando uma consulta analítica precisa de apenas 3 colunas de uma tabela com 50 colunas, o MySQL ainda lê todas as 50 colunas do disco. O formato de row store torna o acesso seletivo a colunas inerentemente ineficiente.

O framework de consulta paralela do PolarDB resolve o gargalo da CPU distribuindo o trabalho de varredura entre vários threads e agregando os resultados no thread principal:

image.png

A consulta paralela rompe o teto de núcleo único e reduz o tempo de consulta para cargas de trabalho intensivas em varredura. Porém, a ineficiência de E/S do row store impõe um limite que a execução paralela sozinha não consegue superar. Eliminar esse teto exige um column store.

Um column store melhora o desempenho em dois níveis:

  • Eficiência de E/S. As consultas leem apenas as colunas necessárias. Os dados em coluna atingem taxa de compressão superior a 10 vezes em comparação ao row store. Combinado com rough indexes (estatísticas MIN/MAX por bloco de dados), grandes blocos de dados irrelevantes podem ser ignorados antes da descompressão. Na arquitetura de computação e armazenamento separados do PolarDB, menos dados transferidos pela rede resultam diretamente em respostas de consulta mais rápidas.

  • Eficiência de CPU. Os dados em coluna são armazenados contiguamente, o que melhora as taxas de acerto do cache da CPU e reduz as paralisações por falha nos caches L1/L2. Dados em coluna contíguos também permitem a vetorização SIMD, multiplicando o throughput de núcleo único.

Termos-chave

Termo

Definição

IMCI

In-Memory Column Index. Implementação do PolarDB de um armazenamento híbrido linha-coluna.

Índice colunar

Índice secundário no InnoDB que armazena dados em formato colunar em vez de formato de linha.

Grupo de linhas

Unidade de organização de dados em um índice colunar. Cada grupo de linhas contém 64.000 linhas.

Pacote de dados

Dados de uma única coluna dentro de um grupo de linhas, armazenados contiguamente e compactados.

Rough index

Estatísticas pré-computadas (MIN, MAX, SUM, contagem de nulos, contagem de linhas) para cada pacote de dados, usadas para ignorar pacotes irrelevantes sem descompactá-los.

Área de Column Store em Memória

Região de memória onde pacotes de dados ativos ficam em cache para execução de consultas. Os dados em coluna são compactados no disco e mantidos em cache nesta área.

Grau de paralelismo (DOP)

Número de threads paralelos usados para executar uma consulta. O Auto DOP define esse valor automaticamente com base nos recursos do sistema.

Modelo Volcano

Modelo de execução de consulta onde cada operador expõe uma interface Next(), puxando dados de operadores filhos uma linha (ou lote) por vez.

Execução vetorizada

Variante do modelo volcano onde cada chamada Next() retorna um lote de linhas em vez de uma única linha, permitindo aceleração SIMD.

Como o IMCI funciona

O IMCI combina quatro inovações técnicas:

  1. Índices colunares no InnoDB. Crie índices colunares em colunas selecionadas usando instruções DDL. Índices colunares usam armazenamento compactado por coluna — significativamente menor que o row store — e residem na Área de Column Store em Memória por padrão. Quando a memória é insuficiente, eles transbordam para o armazenamento compartilhado.

  2. Mecanismo de execução orientado a colunas. O executor do PolarDB acessa dados em lotes de 4.096 linhas e aplica instruções SIMD para processar vários valores em uma única operação de CPU. Todos os operadores principais (Scan, Hash Join, Nested Loop Join, Group By) suportam execução paralela. Em comparação ao executor de linhas do MySQL, o executor de colunas oferece desempenho ordens de magnitude superior em cargas de trabalho analíticas.

  3. Otimizador híbrido linha-coluna. Ao enviar uma consulta, o otimizador avalia o custo de três caminhos de execução — execução serial no row store, consulta paralela no row store e IMCI — e seleciona o plano de menor custo. Um mecanismo de lista de permissões garante que consultas usando tipos de coluna ou operadores não suportados retornem automaticamente ao row store, preservando 100% de compatibilidade com o MySQL.

  4. Isolamento de cargas AP/TP. Configure um nó somente leitura (RO) dedicado como um nó analítico com índices colunares. Consultas analíticas são executadas no nó RO utilizando toda a CPU e memória disponíveis, sem impacto nas cargas de trabalho OLTP executadas em nós de leitura/gravação (RW).

image.png

Arquitetura técnica

Otimizador híbrido linha-coluna

O otimizador decide se executa uma consulta no row store, no mecanismo de consulta paralela ou no IMCI. Isso envolve dois mecanismos: uma lista de permissões para compatibilidade e seleção de plano baseada em custo para desempenho.

Alcançando 100% de compatibilidade com MySQL

Nem toda consulta pode ser executada no IMCI. Duas restrições limitam a cobertura:

  • Cobertura de colunas. Uma consulta que referencia colunas não incluídas em nenhum índice colunar não pode usar o IMCI para essas colunas.

  • Cobertura de operadores. O mecanismo de execução do IMCI é uma reescrita completa, não uma extensão do executor de linhas do MySQL. Alguns tipos de coluna, operadores e formas de expressão ainda não foram implementados no mecanismo IMCI.

image.png

O mecanismo de lista de permissões verifica tipos de dados, operadores, expressões e cenários não suportados (como multi-statements) contra uma lista validada. Se uma consulta passar na lista de permissões, ela estará apta para execução no IMCI. Caso contrário, ela retorna ao executor de linhas nativo do MySQL. Esse fallback garante 100% de compatibilidade: o IMCI acelera o que pode e o MySQL cuida do restante.

Conversão de plano de consulta

A conversão de plano transforma a representação em árvore de sintaxe abstrata (AST) do MySQL em um plano lógico do IMCI. O processo percorre a árvore do plano de execução e reescreve nós AST como operadores relacionais, lidando com conversões implícitas de tipo para manter a compatibilidade com o sistema de tipos flexível do MySQL.

O plano lógico é então otimizado em um plano físico. Além das otimizações padrão (seleção entre Hash Join e Nested Loop Join), o otimizador do IMCI converte subconsultas que o executor do IMCI não consegue lidar diretamente em operações de junção equivalentes.

Seleção tripla baseada em custo

O otimizador do PolarDB escolhe entre três caminhos de execução:

Caminho de execução

Descrição

Compatibilidade

Desempenho em cargas AP

Execução serial no row store

Executor nativo single-thread do MySQL

Mais alta

Mais baixo

Consulta paralela no row store

Execução multithread em dados do row store

Alta

Moderado

IMCI

Execução vetorizada e paralela em índices colunares

Cobertura SQL mais restrita

Mais alto

O otimizador segue este processo:

  1. Analise a instrução SQL e gere um plano lógico. Passe o plano tanto para o otimizador nativo do MySQL quanto para o compilador de planos do IMCI.

  2. Calcule o custo de execução no row store. Se exceder um limiar, tente enviar a consulta para o IMCI.

  3. Se o IMCI não puder executar a consulta, tente gerar um plano de consulta paralela.

  4. Se nem o IMCI nem a consulta paralela conseguirem lidar com a consulta, retorne à execução serial no row store.

Este modelo de custo assume que o IMCI supera a consulta paralela, que por sua vez supera a execução serial. Na prática, um parallel index join em índices de row store às vezes pode ser mais barato que um sort-merge join em um column store. O otimizador pode selecionar o IMCI em casos onde um plano de row store seria mais rápido.

Mecanismo de execução orientado a colunas

O mecanismo de execução do IMCI é uma reescrita completa, independente do executor de linhas do MySQL. Seu objetivo é eliminar dois gargalos fundamentais: sobrecarga de funções virtuais por linha e incapacidade de paralelizar a execução.

Executor paralelo vetorizado

O mecanismo usa um modelo volcano modificado: cada chamada Next() retorna um lote de 4.096 linhas em vez de uma linha por vez. Esse modelo de processamento em lotes permite duas otimizações:

Vetorização. Processar dados em lotes orientados a colunas torna aplicáveis as instruções SIMD. Em vez de uma operação por ciclo de clock da CPU, as instruções SIMD processam vários valores simultaneamente. Combinada com o armazenamento contíguo de colunas, que maximiza a utilização do cache da CPU, a execução vetorizada atinge um throughput de núcleo único significativamente maior que o executor de linhas do MySQL.

image.png

Execução paralela. Scan, Hash Join, Nested Loop Join e Group By suportam execução paralela. Quando o otimizador determina que uma varredura de tabela excede o limiar para execução paralela, ele calcula um DOP recomendado com base na CPU disponível, memória, recursos de E/S, fila de tarefas agendadas, complexidade da consulta e parâmetros configuráveis. Todos os operadores em um plano usam o mesmo DOP. Substitua o DOP para uma consulta específica usando hints.

image.png

O diagrama a seguir mostra a execução de Hash Join no IMCI, ilustrando como paralelização e vetorização funcionam juntas:

image.png

A vetorização aumenta o throughput de núcleo único; o paralelismo rompe o teto de núcleo único. Juntos, eles tornam o mecanismo de execução do IMCI ordens de magnitude mais rápido que o executor de linhas do MySQL em SQL analítico.

Sistema de expressões vetorizado

SQL analítico é intenso em expressões: filtros, projeções, agregações e colunas computadas envolvem avaliação de expressões. No executor de linhas do MySQL, cada avaliação de linha aciona um percurso recursivo na árvore de expressões, com uma chamada de função virtual por nó de expressão por linha. Esse padrão prejudica tanto os caches da CPU quanto a previsão de ramificação.

O sistema de expressões do IMCI substitui o modelo de iterador de árvore por duas otimizações:

  • Processamento em lote com SIMD. Como os dados em coluna são contíguos, a mesma expressão pode ser aplicada a um lote inteiro de valores usando instruções SIMD. O PolarDB reescreve o kernel de expressão para tipos de dados comuns — operações aritméticas (+, -, ×, / e abs) em INT, DECIMAL e DOUBLE — usando instruções AVX512. O throughput de núcleo único melhora várias vezes em comparação à execução escalar.

image.png

  • Layout linear de expressões. Durante a compilação da consulta, as expressões do IMCI são armazenadas como uma árvore (semelhante à estrutura do MySQL). Antes da execução, a árvore é achatada em um array unidimensional em percurso pós-ordem. A execução itera sobre o array linearmente, eliminando completamente chamadas de função recursivas. Esse layout linear também separa dados da computação, o que simplifica a execução paralela.

Armazenamento híbrido linha-coluna

OLTP e OLAP têm requisitos de armazenamento fundamentalmente diferentes. O OLTP precisa de indexação precisa no nível da linha e modificações eficientes de linhas únicas. O OLAP precisa de varredura de colunas em massa e alta compressão. O armazenamento híbrido linha-coluna do PolarDB — usando o mesmo design do Oracle Database In-Memory e do índice columnstore do SQL Server — armazena ambos os formatos simultaneamente em um único mecanismo:

  • Consistência em tempo real. Dados orientados a linhas e a colunas permanecem sincronizados no nível da transação. Dados gravados no row store aparecem em consultas analíticas imediatamente após o commit.

  • Eficiência de custos. Especifique apenas as colunas que precisam de aceleração analítica como índices colunares. Os dados completos continuam no row store. Indexe apenas as colunas que você realmente analisa, não a tabela inteira.

  • Operações simplificadas. Nenhum pipeline de sincronização de dados para manter, nenhuma lacuna de consistência para monitorar.

image.png

A manutenção do column store deve ser leve o suficiente para não degradar o desempenho do OLTP. Se houver conflito, o desempenho do OLTP tem prioridade. Essa restrição molda todas as decisões de design abaixo.

Column store como índice secundário

O IMCI implementa o column store como um índice secundário do InnoDB, em vez de um mecanismo de armazenamento separado. Esse design traz várias vantagens:

  • Reutilização de transações. O InnoDB já aplica operações INSERT, UPDATE e DELETE a todos os índices secundários atomicamente, dentro da mesma transação. O IMCI herda esse framework de transações sem modificações.

  • Reutilização de codificação. Índices colunares usam a mesma codificação de dados que outros índices de row store. Nenhuma conversão de conjunto de caracteres ou collation é necessária ao mover dados entre formatos.

  • Seleção flexível de colunas. Crie índices colunares em qualquer subconjunto de colunas. Adicione ou remova colunas usando DDL. Indexe colunas analíticas de alta cardinalidade (INT, FLOAT, DOUBLE) enquanto mantém colunas grandes usadas apenas para consultas pontuais (TEXT, BLOB) no row store.

  • Reutilização de recuperação. A recuperação de falhas reutiliza o módulo de redo log do InnoDB. Índices colunares em nós RO ou nós standby são reconstruídos a partir do redo log, integrando-se perfeitamente ao processo de replicação física do PolarDB.

  • Gerenciamento de ciclo de vida. Um índice colunar compartilha o ciclo de vida do índice primário, simplificando o gerenciamento de schema.

image.png

No PolarDB, o índice primário e todos os índices secundários são árvores B+. Um índice colunar é logicamente um índice — ele captura todas as inserções, atualizações e exclusões nas colunas indexadas — mas fisicamente armazena colunas independentemente, em vez de codificá-las juntas em uma única linha.

Para a tabela mostrada acima: o índice primário armazena todas as cinco colunas (C1–C5); um índice secundário armazena duas colunas (C2, C1) codificadas juntas em uma árvore B+; o índice colunar armazena três colunas (C2, C3, C4) em formato de coluna dividido e independente.

Quando todas as colunas exigidas por uma consulta são cobertas por um índice colunar, a execução da consulta usa apenas esse índice — sem nunca tocar no índice primário. Esta é a mesma otimização de covering index que o MySQL já suporta, aplicada a dados em formato de coluna. Consultas analíticas em colunas cobertas são executadas dezenas a centenas de vezes mais rápido que consultas equivalentes no row store.

Organização de dados orientados a colunas

Cada coluna em um índice colunar é armazenada em modo de gravação por anexação, sem ordenação. A recuperação de espaço usa rótulos de exclusão e compactação em segundo plano em vez de atualizações no local. Pontos-chave do design:

  • Grupos de linhas. Os registros são organizados em grupos de linhas de 64.000 linhas cada. Dentro de um grupo de linhas, cada coluna é armazenada como um pacote de dados separado.

  • Grupo de linhas ativo. Um grupo de linhas está ativo a qualquer momento, aceitando novas gravações. Quando ele enche, é congelado. Todos os seus pacotes de dados são compactados e liberados no disco, e estatísticas de rough index são computadas para cada pacote.

  • IDs de linha. Cada nova linha recebe um ID de linha. O sistema usa o ID de linha para localizar os dados dessa linha em todos os pacotes de dados de coluna. Um índice de mapeamento de chaves primárias para IDs de linha suporta exclusões e atualizações subsequentes.

  • Rótulos de exclusão. Operações de exclusão definem um bit em um bitmap de exclusão em vez de modificar dados de coluna no local. Operações de atualização combinam um rótulo de exclusão na linha antiga com uma gravação por anexação dos novos dados da linha no grupo de linhas ativo.

  • Compactação em segundo plano. Quando registros inválidos (excluídos) em um grupo de linhas excedem um limiar, a compactação em segundo plano recupera espaço e melhora a densidade de armazenamento para varreduras analíticas.

image.png

Esse design mantém as operações de gravação leves: uma gravação anexa dados de coluna à memória; uma exclusão define um rótulo; uma atualização define um rótulo e anexa. A manutenção do column store adiciona sobrecarga mínima às transações OLTP, e o isolamento no nível da transação é preservado durante todo o processo.

Conversão completa e incremental de linha para coluna

Os índices colunares são preenchidos em dois cenários:

Conversão completa (construção inicial do índice). Ao criar um índice colunar em uma tabela existente, o PolarDB varre o índice primário do InnoDB em paralelo e converte todas as colunas indexadas para o formato de coluna. Esta é uma operação DDL online — ela não bloqueia transações em execução e sua velocidade é limitada apenas pelo throughput de E/S disponível e recursos de CPU.

image.png

Conversão incremental (transações contínuas). Após a criação de um índice colunar, cada transação que modifica colunas indexadas atualiza tanto o row store quanto o column store:

  • Sem IMCI: a transação bloqueia linhas, modifica páginas de dados e libera bloqueios antes do commit.

  • Com IMCI: a transação cria adicionalmente um cache de atualização do column store. Modificações nas páginas de dados são registradas no cache. Antes que a transação libere bloqueios e faça commit, o cache é aplicado ao column store.

image.png

Para transações OLTP típicas, o tempo gasto modificando páginas de dados em memória é uma pequena fração do tempo total da transação. A atualização do column store adiciona latência mínima. Para grandes transações que afetam muitas linhas, as atualizações do column store são aplicadas em tempo real, mas permanecem invisíveis até que a transação faça commit — mantendo a latência de commit dentro de uma faixa estreita. Para cargas de trabalho que toleram algum atraso na atualização dos dados, as atualizações do column store podem ser aplicadas assincronamente para reduzir ainda mais o impacto no desempenho do OLTP.

O isolamento de transações no column store espelha o row store. Cada linha em um grupo de linhas registra o ID da transação que a escreveu. Cada rótulo de exclusão em um bitmap de exclusão registra o ID da transação que o definiu. Consultas AP usam esses IDs de transação para construir um snapshot globalmente consistente, com sobrecarga mínima.

Esquema de rough index

Todos os pacotes de dados são não ordenados e gravados por anexação, portanto, índices colunares não podem suportar filtragem precisa no nível da linha como índices B+ tree ordenados. Em vez disso, o IMCI usa um esquema de rough index baseado em estatísticas pré-computadas para ignorar pacotes de dados irrelevantes antes da descompressão.

Quando um pacote de dados ativo termina a gravação e congela, o sistema computa e armazena estas estatísticas nos metadados do pacote de dados:

  • Valor mínimo

  • Valor máximo

  • Soma dos valores

  • Contagem de valores nulos

  • Contagem total de registros

Essas estatísticas persistem na memória. Para pacotes de dados congelados com exclusões, as estatísticas são atualizadas em segundo plano.

No momento da consulta, o otimizador classifica cada pacote de dados como relevante, irrelevante ou possivelmente relevante com base nos predicados da consulta e nas estatísticas do pacote. Pacotes irrelevantes são ignorados completamente. Para operações de agregação como COUNT e SUM, pacotes relevantes frequentemente podem ser respondidos diretamente a partir de estatísticas pré-computadas, ignorando totalmente a descompressão.

image.png

Rough indexes funcionam melhor para consultas que varrem grandes volumes de dados — exatamente a carga de trabalho alvo do IMCI. Para consultas que localizam um pequeno número de linhas específicas, o otimizador baseado em custo direciona para um índice de row store.

Isolamento de recursos TP/AP

Executar OLTP e OLAP no mesmo cluster cria risco de contenção de recursos: uma grande consulta analítica pode consumir CPU e E/S suficientes para aumentar a latência do OLTP. O PolarDB suporta três modos de implantação para isolar essas cargas de trabalho, usando sua arquitetura write-once-read-many para adicionar nós RO independentes.

Modo

Configuração

Nível de isolamento

Quando usar

Modo 1

IMCI ativado no nó RW

Nenhum — TP e AP compartilham CPU e memória

Carga AP leve; consultas de relatórios em dados importados em lote

Modo 2

IMCI ativado em um nó RO dedicado do tipo AP

CPU e memória totalmente isolados; E/S compartilhado

Carga AP moderada; maioria das implantações HTAP de produção

Modo 3

IMCI ativado em um nó standby dedicado com armazenamento compartilhado independente

CPU, memória e E/S totalmente isolados

Carga AP pesada; SLAs estritos de latência para OLTP

image.png

Além do isolamento no nível de implantação, o Auto DOP limita os recursos que qualquer consulta analítica individual pode consumir. O cálculo do DOP considera a carga atual do sistema, CPU e memória disponíveis e a fila de consultas agendadas — impedindo que uma única consulta grande prive outras requisições de recursos.

Desempenho OLAP

Para resultados de benchmarks, consulte Desempenho do IMCI.