Você Não Precisa de um Data Warehouse: DuckDB é o Suficiente

Você Não Precisa de um Data Warehouse: DuckDB é o Suficiente

12 min de leitura

Deixe-me adivinhar: você tem dados em CSV ou Parquet no S3, ou talvez em uma pasta local. E alguém na sua empresa já sugeriu que vocês precisam de um “data warehouse moderno” como Snowflake ou BigQuery. Afinal, “precisamos escalar”, “precisamos de performance”, “precisamos de uma solução enterprise”.

E com isso vem: configuração de VPC, gerenciamento de credenciais, políticas de IAM, controle de custos, otimização de queries, particionamento de tabelas, e uma conta que pode facilmente chegar a milhares de dólares por mês.

Aqui está uma verdade inconveniente: na maioria dos casos, você não precisa de nada disso.

DuckDB pode analisar seus dados diretamente - onde quer que eles estejam - sem você mover um único byte. Sem servidor. Sem infraestrutura. Sem custo de compute. E provavelmente mais rápido do que muitas soluções “enterprise”.

Deixe-me mostrar por quê.

O Que É DuckDB?

DuckDB é um banco de dados analítico (OLAP) embutido. Pense nele como o “SQLite para analytics”.

Características principais:

  • Zero configuração: Não há servidor para instalar ou gerenciar
  • In-process: Roda diretamente dentro da sua aplicação Python, R, Node.js, etc.
  • OLAP otimizado: Engine vetorizado colunar para consultas analíticas extremamente rápidas
  • Query direto em arquivos: CSV, Parquet, JSON - sem precisar importar primeiro
  • Query remoto: S3, HTTP(S), GCS - lê diretamente da nuvem
  • Integração nativa: Query direto em Pandas DataFrames, Arrow, Polars
  • Free e open source: MIT License, sem vendor lock-in

A diferença fundamental: DuckDB traz o processamento para os dados, não os dados para o processamento.

Por Que Você (Provavelmente) Não Precisa de um Data Warehouse

1. Você Não Está Na Escala Que Pensa Estar

Vamos ser honestos: a maioria das empresas não tem “big data”. Elas têm “medium data” ou até “small data que cresceu um pouco”.

DuckDB pode:

  • Processar terabytes de dados em um laptop comum
  • Ler gigabytes de Parquet comprimido em segundos
  • Fazer joins e agregações em bilhões de linhas
  • Rodar em 500MB de RAM ou em 500GB - ele se adapta

A menos que você tenha dezenas de terabytes sendo consultados simultaneamente por centenas de usuários, você provavelmente não precisa de um data warehouse.

2. Você Está Pagando Para Mover Dados Que Já Estão Onde Precisam Estar

O fluxo tradicional:

  1. Dados gerados → S3/Cloud Storage
  2. ETL: Mover dados do S3 para Snowflake/BigQuery (💰 custo de compute)
  3. Armazenar dados duplicados no warehouse (💰 custo de storage)
  4. Rodar queries (💰 custo de compute de novo)

O fluxo com DuckDB:

  1. Dados gerados → S3/Cloud Storage
  2. Query direto no S3 (✅ zero custo extra)

Exemplo prático:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import duckdb

# Query direto em Parquet no S3 - sem ETL, sem import
resultado = duckdb.sql("""
    SELECT 
        produto,
        SUM(valor) as total_vendas,
        COUNT(*) as num_vendas
    FROM read_parquet('s3://meu-bucket/vendas/*.parquet')
    WHERE data >= '2024-01-01'
    GROUP BY produto
    ORDER BY total_vendas DESC
    LIMIT 10
""").df()

print(resultado)

Isso é tudo. Sem configuração de cluster, sem import de dados, sem conta de warehouse.

3. A Complexidade Operacional Mata Produtividade

Com um data warehouse tradicional:

  • ⏰ Dias ou semanas para provisionar e configurar
  • 🔐 Configuração de VPC, networking, security groups
  • 💳 Gerenciamento de custos e budgets
  • 📊 Monitoramento de performance e queries
  • 🔄 Manutenção de ETL pipelines
  • 👥 Treinamento da equipe em uma nova plataforma
  • 🐛 Debug de problemas de rede, permissões, quota limits

Com DuckDB:

1
pip install duckdb

Pronto. Sua equipe já sabe SQL? Então já sabe usar DuckDB.

Casos de Uso Reais: DuckDB Na Prática

Caso 1: Análise de Logs de Sistemas

Você tem logs em JSON no S3, quer analisar padrões de erro:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import duckdb

# Instalar extensão HTTPFS (uma vez)
duckdb.sql("INSTALL httpfs")
duckdb.sql("LOAD httpfs")

# Configurar credenciais S3
duckdb.sql("""
    SET s3_region='us-east-1';
    SET s3_access_key_id='<sua-key>';
    SET s3_secret_access_key='<sua-secret>';
""")

# Análise direta em JSON comprimido no S3
query = """
SELECT 
    DATE_TRUNC('hour', timestamp) as hora,
    level,
    COUNT(*) as total_eventos,
    COUNT(DISTINCT user_id) as usuarios_afetados
FROM read_json_auto('s3://logs-producao/app-logs-*.json.gz')
WHERE level IN ('ERROR', 'CRITICAL')
  AND timestamp >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY DATE_TRUNC('hour', timestamp), level
ORDER BY hora DESC, total_eventos DESC
"""

resultado = duckdb.sql(query).df()

Performance: DuckDB lê apenas as colunas necessárias e aplica filtros durante a leitura (predicate pushdown).

Caso 2: Join de Múltiplas Fontes

Você tem vendas em Parquet, clientes em CSV, produtos em um dataframe Pandas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import duckdb
import pandas as pd

# Produtos já carregados em memória
produtos_df = pd.read_csv('produtos.csv')

# Query misto: S3 + local + DataFrame
query = """
SELECT 
    v.data,
    p.categoria,
    p.nome_produto,
    COUNT(*) as num_vendas,
    SUM(v.valor) as receita_total,
    AVG(v.quantidade) as quantidade_media
FROM read_parquet('s3://dados/vendas/2024/*.parquet') v
JOIN read_csv('clientes.csv') c ON v.cliente_id = c.id
JOIN produtos_df p ON v.produto_id = p.id
WHERE c.segmento = 'premium'
  AND p.categoria IN ('eletrônicos', 'eletrodomésticos')
GROUP BY v.data, p.categoria, p.nome_produto
ORDER BY receita_total DESC
"""

resultado = duckdb.sql(query).df()

Note: DuckDB faz join entre arquivo S3, arquivo local e DataFrame Pandas sem importar nada primeiro.

Caso 3: Exploratory Data Analysis (EDA) Rápido

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import duckdb

# Resumo estatístico automático de arquivos enormes
duckdb.sql("SUMMARIZE FROM read_parquet('vendas-2024.parquet')").show()

# Saída:
# ┌─────────────┬──────────────┬─────────┬──────────┬──────────┐
# │ column_name │ column_type  │   min   │   max    │   avg    │
# ├─────────────┼──────────────┼─────────┼──────────┼──────────┤
# │ data        │ DATE         │ 2024... │ 2024...  │   NULL   │
# │ valor       │ DECIMAL(10,2)│ 1.50    │ 9999.99  │  342.15  │
# │ quantidade  │ INTEGER      │ 1       │ 500      │   12.3   │
# └─────────────┴──────────────┴─────────┴──────────┴──────────┘

Caso 4: Pipeline de Analytics Sem Infraestrutura

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import duckdb
from datetime import datetime

# Criar conexão persistente
con = duckdb.connect('analytics.duckdb')

# Processar dados e materializar resultados importantes
con.sql("""
    CREATE TABLE vendas_diarias AS
    SELECT 
        DATE_TRUNC('day', data) as data,
        categoria,
        SUM(valor) as total_vendas,
        COUNT(*) as num_transacoes,
        COUNT(DISTINCT cliente_id) as clientes_unicos
    FROM read_parquet('s3://raw-data/vendas/*.parquet')
    WHERE data >= CURRENT_DATE - INTERVAL '90 days'
    GROUP BY DATE_TRUNC('day', data), categoria
""")

# Exportar para Parquet particionado para análises posteriores
con.sql("""
    COPY vendas_diarias 
    TO 'vendas_processadas' 
    (FORMAT PARQUET, PARTITION_BY (data))
""")

# Query rápido nos dados processados
resultado = con.sql("""
    SELECT * FROM vendas_diarias 
    WHERE data >= CURRENT_DATE - INTERVAL '7 days'
    ORDER BY total_vendas DESC
""").df()

con.close()

DuckDB vs. Data Warehouses: Onde DuckDB Vence

Critério DuckDB Snowflake/BigQuery/Redshift
Setup inicial pip install duckdb (5 segundos) Dias/semanas de configuração
Custo mensal $0 $500 - $50,000+
Latência de query ad-hoc Milissegundos Segundos (cold start)
Query em arquivos locais ✅ Nativo ❌ Precisa upload
Query em S3/GCS ✅ Direto ⚠️ Precisa import/external tables
Integração Python/Pandas ✅ Zero-copy ⚠️ Precisa export/import
Funciona offline ✅ Sim ❌ Não
Vendor lock-in ✅ Zero ❌ Alto
Learning curve ✅ SQL padrão ⚠️ SQL + plataforma específica

DuckDB vs. Data Warehouses: Onde Data Warehouses Vencem

Sejamos justos. Há casos onde você realmente precisa de um data warehouse:

1. Concorrência Massiva

  • Centenas de usuários fazendo queries complexas simultaneamente
  • DuckDB é single-process; não escala horizontalmente

2. Dados Mutáveis de Alta Frequência

  • Milhares de UPDATEs/DELETEs por segundo
  • DuckDB é otimizado para OLAP (read-heavy), não OLTP

3. Governança Enterprise Complexa

  • Row-level security com milhares de regras
  • Audit logs detalhados nativos
  • DuckDB tem features básicas de segurança

4. Integração com Ecossistema Específico

  • Se você já tem todo o stack na AWS e precisa integração nativa com Redshift Spectrum, QuickSight, etc.

5. Dados Realmente Massivos com Queries Simultâneas

  • Centenas de terabytes sendo consultados por dezenas de analistas ao mesmo tempo
  • DuckDB processa terabytes, mas é single-machine

A pergunta honesta: Você realmente está nessa escala? Ou está antecipando um problema que talvez nunca tenha?

Performance: DuckDB É Realmente Rápido?

Não confie apenas na palavra deles. Veja os benchmarks oficiais:

TPC-H SF100 (100GB) - Query típica de data warehouse:

  • DuckDB: ~10 segundos (laptop moderno)
  • Sistemas tradicionais: minutos

ClickBench (100M rows) - Queries analíticas reais:

  • DuckDB: Entre os 3 mais rápidos junto com ClickHouse

Por que é tão rápido?

  1. Vectorized execution: Processa milhares de valores por operação
  2. Columnar storage: Lê apenas colunas necessárias
  3. Parallel processing: Usa todos os cores da CPU
  4. Smart compression: Menos I/O
  5. Zero network: In-process elimina serialização

Arquitetura Moderna: DuckDB + Data Lake

A arquitetura moderna não envolve um data warehouse centralizado. Envolve:

Data Lake (S3/GCS)DuckDB para analytics

┌──────────────────────────────────────────┐
│         Object Storage (S3/GCS)          │
│  ┌──────────┐  ┌──────────┐  ┌─────────┐ │
│  │ Raw Data │  │ Curated  │  │ Serving │ │
│  │ (JSON)   │  │ (Parquet)│  │(Parquet)│ |
│  └──────────┘  └──────────┘  └─────────┘ │
└──────────────────────────────────────────┘
            ↓ Query direto
┌──────────────────────────────────────────┐
│              DuckDB (local)              │
│  • Python notebooks                      │
│  • APIs / Microservices                  │
│  • Batch jobs                            │
│  • BI tools (via ODBC)                   │
└──────────────────────────────────────────┘

Benefícios:

  • ✅ Armazenamento barato (S3 = ~$0.023/GB/mês)
  • ✅ Formato aberto (Parquet)
  • ✅ Zero vendor lock-in
  • ✅ Compute on-demand (só roda quando necessário)
  • ✅ Versionamento com Delta Lake / Iceberg

Padrão Híbrido: Quando Usar Ambos

Para alguns cenários, faz sentido usar DuckDB + DW:

DuckDB para:

  • Development e testing local
  • ETL/ELT processing
  • Ad-hoc analysis
  • Prototipagem rápida
  • Data exploration inicial

Data Warehouse para:

  • Dashboards de produção com alta concorrência
  • Queries de usuários finais (não-técnicos)
  • Dados que precisam de updates frequentes

Exemplo de workflow:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1. Desenvolve e testa com DuckDB local
import duckdb

query = """
SELECT 
    categoria,
    DATE_TRUNC('month', data) as mes,
    SUM(valor) as total
FROM read_parquet('s3://raw-data/*.parquet')
GROUP BY categoria, mes
"""

# Testa localmente em amostra
resultado_teste = duckdb.sql(query + " LIMIT 1000").df()

# 2. Quando validado, materializa no warehouse para produção
duckdb.sql(f"""
    COPY ({query}) 
    TO 's3://processed-data/vendas_mensais.parquet'
    (FORMAT PARQUET)
""")

# 3. Warehouse carrega o Parquet processado
# Muito mais barato que processar no warehouse diretamente

Integrações Poderosas

Query em PostgreSQL/MySQL Sem Migração

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import duckdb

# Attach banco existente
duckdb.sql("INSTALL postgres")
duckdb.sql("LOAD postgres")

duckdb.sql("""
    ATTACH 'host=localhost user=user password=pass dbname=production' 
    AS pg (TYPE POSTGRES)
""")

# Join entre PostgreSQL e S3 Parquet
resultado = duckdb.sql("""
    SELECT 
        p.nome,
        s.total_vendas
    FROM pg.produtos p
    JOIN read_parquet('s3://analytics/vendas.parquet') s
        ON p.id = s.produto_id
    ORDER BY s.total_vendas DESC
    LIMIT 10
""").df()

Query em Excel (Sim, Excel!)

1
2
3
4
5
6
7
8
9
duckdb.sql("INSTALL spatial")
duckdb.sql("LOAD spatial")

# Ler Excel direto
resultado = duckdb.sql("""
    SELECT * 
    FROM st_read('relatorio_vendas.xlsx', layer='Vendas')
    WHERE valor > 1000
""").df()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Busca textual em dados
duckdb.sql("""
    CREATE TABLE documentos AS 
    SELECT * FROM read_parquet('documentos.parquet')
""")

duckdb.sql("PRAGMA create_fts_index('documentos', 'id', 'conteudo')")

resultados = duckdb.sql("""
    SELECT id, conteudo, fts_main_documentos.match_bm25(id, 'duckdb analytics') as score
    FROM documentos
    WHERE score IS NOT NULL
    ORDER BY score DESC
""").df()

Como Começar com DuckDB Hoje

1. Instalação

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Python
pip install duckdb

# R
install.packages("duckdb")

# Node.js
npm install duckdb

# CLI standalone
curl -LO https://github.com/duckdb/duckdb/releases/download/v1.5.0/duckdb_cli-linux-amd64.zip
unzip duckdb_cli-linux-amd64.zip
./duckdb

2. Primeiro Script

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import duckdb

# Análise rápida de um CSV enorme
duckdb.sql("""
    SELECT 
        categoria,
        AVG(preco) as preco_medio,
        COUNT(*) as total_produtos
    FROM read_csv('produtos.csv', AUTO_DETECT=TRUE)
    GROUP BY categoria
    ORDER BY total_produtos DESC
""").show()

3. Persistir Resultados

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Criar database persistente
con = duckdb.connect('meu_analytics.duckdb')

# Materializar tabela
con.sql("""
    CREATE TABLE vendas AS
    SELECT * FROM read_parquet('s3://dados/vendas/*.parquet')
""")

# Queries rápidas depois
resultado = con.sql("SELECT * FROM vendas WHERE data > '2024-01-01'").df()

con.close()

4. Integração com Jupyter

1
2
3
4
5
6
7
8
# Em qualquer notebook Jupyter
import duckdb

# Magic SQL (com extensão duckdb-magic)
%load_ext duckdb_magic

# Agora pode usar SQL direto
SELECT * FROM read_parquet('dados.parquet') LIMIT 10

Mitos e Verdades Sobre DuckDB

❌ Mito: “DuckDB é só para dados pequenos”

✅ Verdade: DuckDB processa terabytes eficientemente. A limitação é hardware, não software.

❌ Mito: “Sem servidor significa sem escalabilidade”

✅ Verdade: Escala verticalmente muito bem. Um servidor moderno com 128GB RAM processa MUITO.

❌ Mito: “Não posso usar em produção”

✅ Verdade: Empresas como GitHub, Hugging Face e outras usam em produção.

❌ Mito: “SQL embarcado é lento”

✅ Verdade: DuckDB frequentemente supera sistemas distribuídos para workloads single-machine.

❌ Mito: “Não tem features enterprise”

✅ Verdade: Tem transações ACID, MVCC, secondary indexes, full-text search, window functions, etc.

Quando NÃO Usar DuckDB

Seja claro sobre as limitações:

  1. Você precisa de concorrência de writes de alta frequência → Use PostgreSQL
  2. Centenas de usuários fazendo queries simultaneamente → Use um data warehouse
  3. Você precisa de um sistema distribuído multi-node → Use Spark, ClickHouse ou data warehouse
  4. Compliance requer auditoria nativa detalhada → Use soluções enterprise
  5. Seu time já domina e está satisfeito com a solução atual → Não mude só por mudar

Conclusão: Questione a Complexidade

A indústria de tecnologia ama complexidade. Vendors lucram vendendo soluções para problemas que você não tem. Consultores ganham implementando arquiteturas over-engineered.

Faça a pergunta honesta:

“Eu realmente preciso disso, ou estou apenas seguindo o que ’todo mundo faz’?”

Para a maioria das empresas:

  • Você não tem petabytes de dados
  • Você não tem milhares de usuários concorrentes em analytics
  • Você não precisa de sub-segundo latency em aggregações de terabytes
  • Você precisa de agilidade, baixo custo e simplicidade

DuckDB oferece isso.

Comece simples. Query seus Parquets no S3 com DuckDB. Se e quando você realmente crescer para a escala que precisa de Snowflake (e a maioria nunca chega), migrar é fácil - seus dados já estão em formato aberto.

Mas aposto que você vai descobrir que DuckDB é suficiente. E suficiente é subestimado.


Recursos adicionais:

Próximo passo: Instale DuckDB agora e faça uma query em um arquivo que você já tem. Literalmente, vai levar 2 minutos. Depois me conte se ainda acha que precisa de um data warehouse.