Como construir um warehouse analítico barato com DuckDB e S3
1. Por que DuckDB + S3 é uma alternativa viável a warehouses tradicionais
Warehouses analíticos tradicionais como Snowflake, Redshift e BigQuery oferecem poder computacional imenso, mas com custos que podem escalar rapidamente. Para times enxutos, projetos de médio porte ou análises ad hoc, o custo de licenciamento e gerenciamento de clusters pode ser proibitivo. DuckDB combinado com S3 surge como uma alternativa elegante: zero custo de licenciamento, arquitetura serverless e sem necessidade de gerenciar infraestrutura.
DuckDB é um banco de dados SQL embarcado, otimizado para consultas analíticas, que roda no mesmo processo da aplicação. Ele não exige servidores dedicados — você executa queries diretamente em arquivos Parquet armazenados no S3. O resultado é um warehouse analítico funcional com custo apenas de armazenamento S3 (centavos por GB/mês) e processamento (quando você executa as queries localmente ou em uma instância EC2 mínima).
Casos de uso ideais incluem: análises exploratórias, dashboards internos, pipelines de dados de times de dados pequenos (1-5 pessoas), e processamento de datasets de até centenas de gigabytes. Para cenários onde a concorrência de usuários é baixa e o volume de dados não exige clusters distribuídos, DuckDB + S3 entrega performance comparável a soluções caras.
2. Configuração do ambiente: instalando DuckDB e conectando ao S3
A instalação é trivial. No terminal, para a CLI:
# macOS (Homebrew)
brew install duckdb
# Linux (download direto)
curl -L https://github.com/duckdb/duckdb/releases/download/v1.1.3/duckdb_cli-linux-amd64.zip -o duckdb.zip
unzip duckdb.zip
./duckdb
Para Python (recomendado para pipelines):
pip install duckdb
Com o DuckDB instalado, ative a extensão httpfs para acesso ao S3:
INSTALL httpfs;
LOAD httpfs;
Configure as credenciais AWS. A forma mais segura é usar variáveis de ambiente:
SET s3_region='us-east-1';
SET s3_access_key_id='SUA_ACCESS_KEY';
SET s3_secret_access_key='SUA_SECRET_KEY';
Ou, se preferir usar perfil IAM configurado via AWS CLI, DuckDB respeita as credenciais do perfil padrão.
3. Estrutura de dados no S3: organização de buckets e formatos de arquivo
A organização do bucket impacta diretamente a performance das consultas. Adote particionamento por colunas de filtro frequentes, como data, região ou categoria:
s3://meu-warehouse/vendas/
├── ano=2024/
│ ├── mes=01/
│ │ ├── vendas_2024_01_01.parquet
│ │ └── vendas_2024_01_02.parquet
│ └── mes=02/
│ └── vendas_2024_02_01.parquet
└── ano=2025/
└── mes=01/
└── vendas_2025_01_01.parquet
O formato Parquet é obrigatório para performance. Ele armazena dados em colunas, com compressão por padrão (Snappy), e permite que DuckDB leia apenas as colunas necessárias. Evite CSV ou JSON para dados além de alguns MBs — o desempenho degrada drasticamente.
4. Ingestão e transformação de dados com DuckDB
Carregar dados do S3 é direto com funções como read_parquet():
CREATE TABLE vendas_brutas AS
SELECT * FROM read_parquet('s3://meu-warehouse/vendas/**/*.parquet');
Para CSVs brutos (fonte comum de dados externos):
CREATE TABLE clientes AS
SELECT * FROM read_csv_auto('s3://meu-warehouse/raw/clientes_*.csv');
Transformações com SQL puro são poderosas. Exemplo de pipeline de limpeza e agregação:
WITH vendas_limpas AS (
SELECT
id_venda,
cliente_id,
data,
valor,
CASE WHEN valor < 0 THEN 0 ELSE valor END AS valor_corrigido
FROM vendas_brutas
WHERE data >= '2024-01-01'
),
resumo_mensal AS (
SELECT
strftime(data, '%Y-%m') AS mes,
COUNT(*) AS total_vendas,
SUM(valor_corrigido) AS receita,
AVG(valor_corrigido) AS ticket_medio
FROM vendas_limpas
GROUP BY mes
)
SELECT * FROM resumo_mensal ORDER BY mes;
Para exportar resultados transformados de volta para S3 como Parquet:
COPY (SELECT * FROM resumo_mensal) TO 's3://meu-warehouse/analytics/resumo_mensal.parquet' (FORMAT PARQUET);
5. Consultas analíticas eficientes: otimização e tuning
Use EXPLAIN ANALYZE para entender o plano de execução:
EXPLAIN ANALYZE SELECT COUNT(*) FROM vendas_brutas WHERE ano = 2024;
Dicas práticas de otimização:
- Filtragem precoce: sempre filtre o máximo possível antes de joins ou agregações.
- Projeção de colunas: evite
SELECT *em tabelas largas — especifique apenas as colunas necessárias. - Ordenação: dados ordenados por colunas de filtro (ex: data) aceleram consultas que usam esses filtros.
- Paralelismo: DuckDB usa múltiplos threads por padrão. Ajuste conforme seu hardware:
SET threads = 4;
SET memory_limit = '2GB';
O cache local também ajuda: DuckDB mantém dados recentes em memória, então consultas repetidas são mais rápidas.
6. Automatizando pipelines com scripts e orquestração leve
Um pipeline diário em Python com DuckDB:
import duckdb
import os
from datetime import datetime, timedelta
# Conecta ao DuckDB (banco efêmero ou persistente)
con = duckdb.connect()
# Configura S3
con.execute("INSTALL httpfs; LOAD httpfs;")
con.execute(f"SET s3_region='us-east-1'")
con.execute(f"SET s3_access_key_id='{os.environ['AWS_ACCESS_KEY_ID']}'")
con.execute(f"SET s3_secret_access_key='{os.environ['AWS_SECRET_ACCESS_KEY']}'")
# Data de processamento (D-1)
data_processamento = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
ano, mes, dia = data_processamento.split('-')
# Pipeline: lê CSV bruto, transforma, escreve Parquet
con.execute(f"""
CREATE TABLE daily_sales AS
SELECT
id,
cliente,
data,
valor,
CURRENT_TIMESTAMP AS processed_at
FROM read_csv_auto('s3://meu-warehouse/raw/vendas_{ano}{mes}{dia}.csv')
WHERE valor IS NOT NULL;
""")
con.execute(f"""
COPY daily_sales TO 's3://meu-warehouse/vendas/ano={ano}/mes={mes}/vendas_{data_processamento}.parquet'
(FORMAT PARQUET, COMPRESSION SNAPPY);
""")
print(f"Pipeline concluído para {data_processamento}")
con.close()
Orquestre com cron (Linux/Mac):
0 6 * * * /usr/bin/python3 /home/user/pipeline_diario.py >> /var/log/duckdb_pipeline.log 2>&1
Ou com GitHub Actions para pipelines mais complexos — zero custo de infra.
7. Governança e segurança: permissões, versionamento e backups
Política IAM mínima para o bucket S3:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::meu-warehouse",
"arn:aws:s3:::meu-warehouse/*"
]
}
]
}
Ative o versionamento no bucket S3 para permitir rollback de dados corrompidos. Para backup de metadados e esquemas:
-- Exportar esquema de todas as tabelas
SELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'main'
ORDER BY table_name, ordinal_position;
Use SHOW TABLES e DESCRIBE nome_tabela para documentação rápida.
8. Limitações e quando migrar para um warehouse tradicional
DuckDB não é bala de prata. Suas limitações principais:
- Memória RAM: DuckDB é in-memory. Se seu dataset não couber na RAM disponível, a performance cai drasticamente (swap para disco). Para datasets > 100GB, considere Snowflake ou Redshift.
- Concorrência: DuckDB não é multi-usuário nativo. Cada processo DuckDB é single-session. Para múltiplos usuários simultâneos, você precisaria de uma camada de pooling (ex: usando
duckdbem modo servidor experimental) ou migrar. - Escala: Consultas que exigem processamento distribuído (ex: shuffle de dados massivos entre nós) são inviáveis.
Cenários para migrar: times com mais de 10 analistas concorrentes, datasets acima de 1TB, ou necessidade de integração com ferramentas de BI que exigem conexão JDBC/ODBC nativa (DuckDB oferece, mas com limitações de concorrência).
Para a maioria dos casos de médio porte, porém, DuckDB + S3 é uma alternativa sólida, barata e surpreendentemente rápida. Você constrói um warehouse analítico funcional por centavos, sem abrir mão de SQL poderoso e performance.
Referências
- Documentação oficial do DuckDB - Extensão httpfs — Guia completo para configurar acesso a S3, GCS e Azure Blob Storage com DuckDB.
- DuckDB + S3: Analytical Workloads on Object Storage — Tutorial oficial sobre como ler e escrever dados no S3 usando DuckDB.
- AWS IAM Best Practices for S3 Buckets — Documentação AWS sobre políticas de segurança mínimas para buckets S3.
- Parquet File Format: Why It Matters for Analytics — Explicação técnica do formato Parquet e por que ele é ideal para warehouses analíticos.
- Building a Data Lake on S3 with DuckDB — Artigo da MotherDuck (empresa por trás do DuckDB) sobre construção de data lakes baratos com S3.
- DuckDB Performance Tuning Guide — Guia oficial de otimização de performance, incluindo ajuste de threads, memória e planos de execução.
- GitHub Actions para orquestração de pipelines de dados — Documentação oficial sobre como usar GitHub Actions para automatizar pipelines de dados sem custo de infraestrutura.