
OLAP em JavaScript: bibliotecas e exemplos práticos
Publicado em:
Tempo de leitura: 10 min
Tema: Tecnologia
Autor: Leandro Valencia
Como fazer analítica do tipo OLAP em JavaScript: DuckDB-Wasm, Apache Arrow, Arquero, Perspective, SQL.js e TinyBase, com exemplos e quando usar cada uma.
Índice
- O panorama: motores completos vs. ferramentas leves
- DuckDB-Wasm: o motor OLAP completo no navegador
- Apache Arrow (JS) + Arquero: formato colunar mais transformação estilo dplyr
- Perspective: motor de pivotamento para dashboards em tempo real
- SQL.js: SQLite em WebAssembly, simples mas não colunar
- TinyBase: store reativo leve, não um motor OLAP
- Tabela comparativa rápida
- Como escolher
O panorama: motores completos vs. ferramentas leves
Antes de entrar biblioteca por biblioteca, uma distinção útil. Em JavaScript há duas categorias de solução para "preciso agregar dados sem bater no meu banco de produção":
Motores OLAP reais compilados para WebAssembly. Executam SQL analítico com armazenamento colunar, vetorização e otimizador de consultas, igual a um ClickHouse ou um BigQuery, mas rodando dentro do processo do navegador ou do Node. DuckDB-Wasm é o representante principal.
Ferramentas de transformação e agregação em memória. Não são motores de banco de dados; são bibliotecas que manipulam estruturas de dados já carregadas (arrays, tabelas Arrow, stores reativos) com operações do tipo groupBy, sum ou pivotamento. Arquero, Perspective e TinyBase caem aqui, cada uma com um enfoque distinto.
SQL.js fica num ponto intermediário: é um motor de banco de dados real (SQLite), mas orientado a linhas, não colunar, então não escala tão bem em cargas puramente analíticas, embora seja muito usado como substituto leve.
DuckDB-Wasm: o motor OLAP completo no navegador
DuckDB-Wasm é a compilação do DuckDB —o motor analítico embutido que já mencionamos no guia de OLAP como a opção padrão para datasets que cabem numa máquina— para WebAssembly. Roda tanto no navegador quanto no Node, sem servidor, com o mesmo motor colunar vetorizado e o mesmo dialeto SQL compatível com PostgreSQL da versão nativa.
É a opção mais potente desta lista porque não é uma simulação de OLAP: é um otimizador de consultas de verdade, com suporte para ler Parquet, CSV e JSON diretamente, inclusive por HTTP range requests, sem baixar o arquivo completo.
Quando usar: quando você precisa executar consultas SQL reais —agregações, JOINs, janelas— sobre datasets de tamanho moderado (de alguns MB até algumas centenas de MB) diretamente no cliente, sem infraestrutura de backend. É a escolha natural para dashboards de analítica embutida que carregam um export de dados, ferramentas de exploração de dados no cliente, ou para evitar mandar consultas pesadas a um servidor quando o arquivo já vive no navegador do usuário.
Um exemplo simplificado de como fica uma consulta contra um arquivo Parquet depois que o motor está inicializado e conectado:
const result = await connection.query(`
SELECT pais, SUM(importe) AS ingresos
FROM read_parquet('ventas.parquet')
GROUP BY pais
ORDER BY ingresos DESC
`);
console.table(result.toArray());
A inicialização (escolher o bundle de WebAssembly certo, subir o worker, abrir a conexão) tem vários passos e muda entre versões, então não a reproduzo aqui: consulte a documentação oficial do DuckDB-Wasm para o setup exato da versão que você instalar.
Apache Arrow (JS) + Arquero: formato colunar mais transformação estilo dplyr
Essas duas bibliotecas costumam ir juntas, e convém entendê-las em separado.
Apache Arrow não é um motor de consultas: é um formato de dados colunar em memória, padronizado entre linguagens (há implementações em Python, R, Java, C++ e JavaScript, entre outras). Seu valor está em que muitas ferramentas de dados —incluindo DuckDB-Wasm— podem ler e produzir Arrow diretamente, então mover dados entre elas não exige serializar para JSON nem reconstruir estruturas: compartilham o mesmo layout de memória.
Arquero é uma biblioteca de transformação de dados para JavaScript inspirada explicitamente no dplyr do R. Trabalha sobre tabelas colunares —arrays, arrays tipados ou colunas Arrow— e expõe uma API encadeável com verbos como filtrar, agrupar, agregar ou unir tabelas.
Quando usar: quando você já tem dados em formato Arrow (por exemplo, exportados de um pipeline em Python ou devolvidos pelo DuckDB-Wasm) e quer encadear transformações do tipo roll-up ou agregação diretamente em JavaScript, sem escrever SQL. É uma boa opção para notebooks de dados em JS, ferramentas de exploração interativa ou quando o time já pensa em termos de dplyr/pandas e prefere essa sintaxe ao SQL.
Um exemplo simplificado de agregação com Arquero sobre uma tabela já carregada:
import { table } from 'arquero';
const ventas = table({
pais: ['ES', 'MX', 'ES', 'AR'],
importe: [42, 17, 88, 12],
});
const resumen = ventas
.groupby('pais')
.rollup({ ingresos: (d) => op.sum(d.importe) });
console.log(resumen.objects());
A API exata de importação, os nomes das funções de agregação (op.sum, op.mean, etc.) e como carregar uma tabela Arrow com fromArrow() convém verificar na documentação oficial do Arquero, porque variam entre versões e conforme você use o bundle que inclui Arrow ou o importe separadamente.
Perspective: motor de pivotamento para dashboards em tempo real
Perspective é um motor de agregação e pivotamento construído em C++ e compilado para WebAssembly, com bindings para JavaScript. Nasceu dentro do J.P. Morgan para dashboards financeiros internos e hoje é um projeto open source sob a Fundação FINOS.
O que distingue o Perspective das demais opções desta lista é que ele foi desenhado especificamente para dados que mudam em tempo real: suporta streaming de atualizações, pivotamento interativo tipo tabela dinâmica (agrupar linhas e colunas, aplicar agregações, ordenar) e vem com seus próprios componentes visuais (<perspective-viewer>) prontos para inserir numa página.
Quando usar: quando o caso de uso é um dashboard interativo em que o usuário final manipula a vista —arrasta dimensões, muda agregações, filtra— e os dados subjacentes se atualizam ao vivo, por exemplo um painel de trading, um monitor de métricas operacionais ou um BI embutido no seu produto. Se você só precisa rodar uma consulta pontual e mostrar um resultado fixo, é mais motor do que precisa; para isso encaixa melhor DuckDB-Wasm ou Arquero.
SQL.js: SQLite em WebAssembly, simples mas não colunar
SQL.js é uma compilação do SQLite para WebAssembly que permite rodar um banco de dados SQLite completo dentro do navegador, sem backend. É provavelmente a biblioteca mais veterana desta lista e a mais fácil de adotar se você já conhece SQL básico.
Aqui é preciso ser honesto sobre os limites: SQLite é um banco de dados orientado a linhas, igual ao Postgres ou ao MySQL. Não tem armazenamento colunar, nem vetorização, nem otimizador pensado para varrer milhões de linhas e agregá-las. Não é um motor OLAP no sentido técnico do termo.
Ainda assim, é muito usado como alternativa leve para análises pequenas no cliente: datasets de alguns milhares ou dezenas de milhares de linhas, em que a diferença de desempenho frente a um motor colunar de verdade não se nota, e em que a vantagem é a simplicidade e a maturidade da biblioteca.
Quando usar: para análise exploratória de datasets pequenos no navegador, protótipos rápidos, ou quando você precisa de SQL completo (incluindo escritas e transações) mais do que de desempenho agregando milhões de linhas. Se o dataset crescer além disso, migre para DuckDB-Wasm.
TinyBase: store reativo leve, não um motor OLAP
TinyBase é um store de dados reativo pensado para o estado de aplicações JavaScript, com um tamanho de biblioteca bem pequeno. Não foi desenhado como motor analítico: seu propósito principal é sincronização de estado, persistência local e reatividade (a UI se atualiza sozinha quando os dados mudam), mais próximo em espírito de bibliotecas de gerenciamento de estado do que de um banco de dados analítico.
Eu o incluo nesta lista porque ele oferece utilitários de agregação simples —contar, somar, calcular a média sobre uma tabela— que em apps pequenas cobrem necessidades que, de outro modo, exigiriam montar um motor mais pesado.
Quando usar: quando a "análise" de que você precisa é na verdade uma agregação simples sobre dados que já vivem no estado da sua app —um contador, um total, uma média que se atualiza ao vivo— e você não quer adicionar um motor SQL completo só por isso. Eu não o escolheria para nada que se pareça com um dashboard multidimensional ou com consultas ad-hoc.
Tabela comparativa rápida
| Biblioteca | O que é | Motor real de OLAP | Melhor para |
|---|---|---|---|
| DuckDB-Wasm | DuckDB compilado para WASM | Sim, colunar e vetorizado | SQL analítico completo no cliente ou no Node |
| Apache Arrow (JS) + Arquero | Formato colunar + transformação estilo dplyr | Formato sim, motor de consultas não | Pipelines de transformação em JS sem SQL |
| Perspective | Motor de pivotamento em WASM (FINOS) | Sim, orientado a agregação interativa | Dashboards em tempo real com pivotamento |
| SQL.js | SQLite compilado para WASM | Não (orientado a linhas) | Análises pequenas, SQL simples no cliente |
| TinyBase | Store reativo leve | Não | Agregações simples sobre o estado da app |
Como escolher
Se você precisa de SQL de verdade sobre um arquivo Parquet ou CSV de tamanho respeitável, sem backend: DuckDB-Wasm, sem hesitar.
Se você já trabalha com dados em formato Arrow e prefere encadear transformações em JavaScript em vez de escrever SQL: Arquero.
Se está construindo um dashboard interativo em que o usuário pivota dados que mudam ao vivo: Perspective.
Se o dataset é pequeno e você só quer SQL básico, sem pretensões de desempenho colunar: SQL.js.
Se a única coisa de que precisa é um contador ou um total reativo dentro do estado da sua app: TinyBase, e provavelmente nem precisa pensar em termos de OLAP.
Em todos os casos, antes de escrever código de produção, revise a documentação oficial da versão que você instalar: as APIs de inicialização (sobretudo no DuckDB-Wasm e no Perspective, que dependem de workers e bundles de WebAssembly) mudam com certa frequência entre versões.
Perguntas frequentes
Existe um motor OLAP colunar nativo em JavaScript, sem WebAssembly?
Não de forma comparável ao DuckDB ou ao ClickHouse. Os motores colunares vetorizados de verdade são escritos em C++ ou Rust e chegam ao JavaScript compilados para WebAssembly (DuckDB-Wasm, Perspective). JavaScript puro não tem um motor desse tipo com adoção equivalente.
Posso usar DuckDB-Wasm num backend Node, não só no navegador?
Sim. DuckDB-Wasm roda tanto no navegador quanto no Node, embora para um backend puro também exista o binding nativo do DuckDB para Node, que evita a camada de WebAssembly. Qual convém depende de você precisar compartilhar código entre cliente e servidor.
SQL.js serve para substituir um banco de dados OLAP de verdade?
Não para cargas grandes. SQL.js é SQLite orientado a linhas; funciona bem para análises pequenas no cliente, mas não escala como um motor colunar em datasets de milhões de linhas.
Arquero precisa do Apache Arrow para funcionar?
Não para o uso básico sobre arrays comuns. O Arrow se torna relevante quando você quer interoperar com dados que já vêm nesse formato (por exemplo, a partir do DuckDB-Wasm) ou exportar resultados para Arrow.
Posts Relacionados
Continue explorando conteúdo similar que pode te interessar

IA para jurídico: checklist de privacidade e DPA ao adotar
Checklist para equipes jurídicas e de compliance: o que exigir de um fornecedor de IA antes de assinar — DPA, retenção, opt-out de treinamento e certificações.

Qwen vs Gemma: como escolher seu modelo local no Ollama
Guia prático para escolher entre Qwen e Gemma ao rodar modelos de IA em local: código, hardware modesto, tarefas multilíngues e uso geral com Ollama.

DuckDB, ClickHouse, Druid ou Pinot: como escolher o OLAP
DuckDB, ClickHouse, Druid e Pinot resolvem problemas diferentes. Árvore de decisão e tabela comparativa para escolher o motor OLAP certo para o seu caso de uso.
Alianças
Ferramentas que uso todos os dias, com melhores condições para a comunidade.