PostgreSQL com extensões pg_vexec e MergeTree fica a só 3x mais lento que o ClickHouse
Igor Suhorukov construiu três extensões sem tocar no core do PostgreSQL 19: um executor vetorizado, uma porta do mecanismo de armazenamento MergeTree do ClickHouse e um access method que evita bloat em UPDATE. O resultado reduz a distância para o ClickHouse em benchmarks de 39x para 3x.
O problema que gera quatro bancos no mesmo sistema
O engenheiro russo Igor Suhorukov descreveu, em post publicado no Planet PostgreSQL↳PostgreSQL11 conteúdosPostgreSQL via SSL com GolangData · abr 20195 itens legais sobre data types do PostgreSQLData · mar 20195 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data →, uma conversa com um arquiteto que mantém quatro bancos em produção: PostgreSQL para OLTP, ClickHouse para dados de observabilidade↳Observabilidade11 conteúdosObservabilidade para APIs: os desafios e benefícios dessa abordagemDev (Back & Front) · jan 2025Falhas em Observabilidade afetam os Apps e a Segurança das OrganizaçõesDev (Back & Front) · nov 2023ADK Java 1.0: O Google quer que você pare de gambiarra Python no seu backendMarketing Tech · abr 2026Ver tudo em DevSecOps → e analytics web, Elasticsearch para busca textual e MongoDB "por razões históricas". Entre eles, pipelines de ETL e CDC, e desenvolvedores de plantão caçando divergência de resultado entre sistemas.
É um cenário comum em times que cresceram rápido: cada carga de trabalho ganhou o banco "certo" para o problema do momento, e a conta da complexidade operacional chegou depois. Suhorukov resolveu testar se dava para devolver parte dessa carga a um único motor, sem abrir mão de desempenho analítico.
A menos que você seja Big Tech, por que acumular a complexidade de manter vários sistemas?
Unless you're Big Tech, why pile up the complexity of maintaining several systems?Igor Suhorukov, autor do projeto, em post no Planet PostgreSQL
pg_vexec: um executor vetorizado sem patch no core
O ponto de partida foi portar o Apache Cloudberry (o fork aberto do Greenplum) para extensões do PostgreSQL 19, o que trouxe o ORCA, planejador baseado em custo do Greenplum, para cima do núcleo padrão. Sobre esse planejador, Suhorukov escreveu o pg_vexec, um executor vetorizado cujos nós (VecScan, VecHashJoin, VecAgg, VecSort) entram no plano de execução pelos mecanismos de extensão padrão do Postgres e competem por custo com os nós tradicionais.
Internamente, o executor processa lotes de 1.024 linhas em formato colunar, com kernels vinculados a OIDs de função; onde não há kernel dedicado, o interpretador de expressões padrão do Postgres entra em ação dentro do próprio nó. A primeira medição no ClickBench, porém, decepcionou: com o planejador padrão sobre heap, o pg_vexec cortou apenas 19% do tempo médio geométrico (de 625 para 506 ms), e sob ORCA, 18%.
O profiling revelou o gargalo: os kernels vetorizados consumiam só 0 a 2% do tempo de execução. O resto ia para deformar linhas largas (51 a 86% dos ciclos de um GROUP BY) e copiar páginas inteiras (26 a 47%). Com linhas de cerca de 1,4 KB, cabem 5 ou 6 por página, e um lote de 1.024 linhas se espalha por aproximadamente 180 páginas, mesmo quando a consulta só precisa de 3 das 105 colunas da tabela de benchmark.
O problema de fundo não era a vetorização, era o heap. A API de table access method do Postgres entrega linhas uma a uma por meio de um slot, e scan_begin() nem recebe a lista de colunas necessárias. Não há ponto de extensão para pular páginas. Uma simulação desse salto de páginas tornou as mesmas consultas do ClickBench de 8 a 100 vezes mais rápidas, mas só no papel.
MergeTree dentro do Postgres: a extensão ch_table_engines
Suhorukov testou armazenamentos colunares existentes no ecossistema Postgres, como Citus columnar e Hydra, mas todos entregam dados pela mesma API de slot, linha a linha. A saída do fork patchado do Greenplum (PAX e AOCO) exigia um core modificado, exatamente o que ele queria evitar.
A solução foi portar o mecanismo de armazenamento MergeTree, da própria biblioteca dbms do ClickHouse, como extensão: ch_table_engines. De cerca de 150 submódulos do ClickHouse, apenas 28 eram necessários; a linkagem estática gera libchte_engine.so. Não dava para usar a implementação StorageMergeTree pronta, pensada para um único processo multithread: quando um segundo processo tenta acessar o mesmo diretório, o ClickHouse recusa com "Another server instance in same directory is already running" — e o Postgres cria um processo por conexão. Foi preciso trabalho de adaptação específico para contornar essa diferença de modelo de execução.
O uso, do lado do desenvolvedor, é direto:
-- postgresql.conf: shared_preload_libraries = 'ch_table_engines'
CREATE EXTENSION ch_table_engines;
CREATE TABLE hits (...) USING mergetree
WITH (order_by = 'CounterID, EventDate, UserID', storage = 'pages');Mas MergeTree sozinho, sem o executor vetorizado, perde até para o heap comum. Sob ORCA, as consultas TPC-H SF1 levaram 61,8 s contra 17,2 s do heap com o executor padrão; no TPC-DS, 380,5 s contra 58,8 s. Só com o pg_vexec acoplado é que os mesmos testes caíram para 6,9 s e 48,6 s, respectivamente.
Do heap cru a 3x do ClickHouse
A combinação de MergeTree com pg_vexec levou o tempo médio geométrico do ClickBench de 715 ms (heap sem vetorização) para 148 ms já na primeira versão, segundo a medição registrada por Suhorukov no dia 5 de outubro (sem indicação do ano na fonte). Depois vieram meses de ajuste fino, incluindo reescrever comparações em SSE2 com movemask (com ajuda de um LLM↳LLMs48 conteúdosConsiderações básicas de hardware para modelos de linguagem em código aberto: Memória, Desempenho e ViabilidadeMarketing Tech · out 2025Modelos de linguagem sob ataque: o lado obscuro da IA generativaDevSecOps · mai 2025Criando um LLM – modelo de linguagem de grande escala – do zero com TransformersAI · abr 2024Ver tudo em AI →), corrigir um branch ausente que fazia o VecHashJoin montar mais de 2 milhões de lotes de uma linha só, e codificar colunas de baixa cardinalidade como índices em um dicionário no estilo LowCardinality do ClickHouse.
| Configuração | Tempo médio geométrico |
|---|---|
| Heap, sem vetorização | 715 ms |
| MergeTree + pg_vexec (versão inicial) | 148 ms |
| MergeTree + pg_vexec (versão final, 10 milhões de linhas) | 49,9 ms |
| ClickHouse, mesma máquina e mesmos dados | 16,8 ms |
No laptop usado para o teste, o PostgreSQL vanilla era 39 vezes mais lento que o ClickHouse nessas consultas; com as três extensões combinadas, a distância caiu para cerca de 3 vezes. É um resultado de bancada, em uma única máquina, não um benchmark distribuído de produção — mas mostra que o gargalo histórico do Postgres em analytics não é fatalidade do modelo relacional, é decisão de armazenamento e executor.
iheap: UPDATE sem inchar a tabela
A segunda frente do projeto ataca um problema crônico de quem já operou Postgres sob transações longas e UPDATE frequente: cada atualização cria uma nova versão da linha, tuplas mortas se acumulam e o autovacuum sofre. Suhorukov respondeu com iheap, um access method que sobrescreve a linha no mesmo TID; a versão antiga vai para um log de undo, reconstruído apenas quando um snapshot de leitura precisa dela.
A ideia lembra o zheap, projeto que passou anos tentando entrar no core do Postgres antes de ser abandonado. A diferença é que iheap não exige patch no core: os mecanismos já disponíveis no PostgreSQL 19, do resource manager de WAL customizado aos horizontes de visibilidade, bastam para implementá-lo como extensão.
-- postgresql.conf: shared_preload_libraries = 'pg_inplace_update_am'
CREATE EXTENSION pg_inplace_update_am;
CREATE TABLE accounts (id int PRIMARY KEY, balance int) USING iheap;
ALTER TABLE old_table SET ACCESS METHOD iheap; -- converte tabela existenteComo o undo fica no próprio fork principal da tabela, WAL, recuperação de falha, réplicas, backups e replicação lógica funcionam como em qualquer tabela heap. Locks de linha também viram registros de undo, o que elimina MultiXacts e o ciclo de freeze. E um fork do btree, o dmbtree, marca a entrada antiga como apagada em vez de criar uma nova em todo índice da tabela: só os índices cujas chaves mudaram recebem entrada nova.
O que muda (e o que ainda não muda) para quem opera banco
Em resumo: o projeto de Suhorukov não é um recurso do PostgreSQL pronto para produção, é uma prova de conceito de um desenvolvedor isolado, construída inteiramente fora do core, sobre o PostgreSQL 19. Antes de cogitar substituir ClickHouse por Postgres em qualquer sistema real, vale separar o que o material comprova do que ainda é promessa.
O que já é argumento sólido para o DBA brasileiro avaliar:
- A API de table access method do Postgres aceita armazenamentos colunares completos via extensão, sem fork do core, o que reduz o risco de ficar preso a um patch não mantido;
- Consolidar OLTP e analytics numa única engine elimina pipeline de CDC, elimina divergência entre sistemas e simplifica backup, réplica e MVCC, porque continuam sendo os mecanismos padrão do Postgres;
iheapataca de frente um problema real de autovacuum e bloat sobUPDATEintenso, sem recorrer a um fork como o zheap tentou por anos.
O que ainda pesa contra adoção imediata:
- As três extensões (
pg_vexec,ch_table_engines,iheap) não estão em nenhum repositório oficial; linkar estaticamente 28 submódulos do ClickHouse dentro de uma.sode extensão é uma manutenção de build nada trivial para manter atualizada; - O benchmark roda num laptop, em um único nó: ClickHouse em cluster distribuído, para petabytes, continua em outra categoria de escala, que o próprio autor reconhece não ser o alvo do projeto;
iheapreimplementa, por fora, garantias de visibilidade e recuperação que levaram anos de revisão quando algo parecido (zheap) tentou entrar no core oficial, isso pede testes extensivos de crash recovery antes de qualquerUPDATEde produção passar por ali.
Para quem só precisa de JOINs consistentes entre OLTP e um punhado de tabelas largas de métricas, sem escala de Big Tech, a arquitetura aponta uma direção legítima: menos sistemas, menos ETL, menos gente de plantão caçando divergência de dado. Mas a régua de qualquer DBA continua a mesma de sempre: antes de trocar ClickHouse por extensão experimental, entenda o plano de execução, valide o índice certo e teste o pg_dump, a réplica e a recuperação de falha sob carga real antes de confiar neles em produção.
Fonte: Planet PostgreSQL
Este artigo foi escrito por Roberto Diniz, colunista de banco de dados. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.
Como fazer upgrade major do PostgreSQL sem downtime em cluster distribuído com Spock
Ahsan Hadi, da pgEdge, testou a migração de PostgreSQL 17 para 18 num cluster multi-master com Spock e documentou as duas armadilhas que não aparecem em nenhum status check.









