Como usar o DuckDB para análises ad hoc em arquivos Parquet e CSV
1. Introdução ao DuckDB e seu papel em análises ad hoc
DuckDB é um sistema de gerenciamento de banco de dados OLAP (Online Analytical Processing) embutido, projetado especificamente para consultas analíticas de alto desempenho. Diferente de bancos relacionais tradicionais como PostgreSQL ou MySQL, o DuckDB é otimizado para workloads de análise de dados, suportando processamento columnar e execução vetorizada.
Seu papel em análises ad hoc é revolucionário: permite que analistas e engenheiros de dados explorem rapidamente arquivos Parquet e CSV sem necessidade de infraestrutura complexa. As principais vantagens incluem:
- Zero configuração: instalação simples e execução imediata
- Processamento local: sem dependência de servidores remotos
- Integração nativa com S3/MinIO: acesso direto a data lakes
- Suporte a formatos modernos: Parquet, Arrow, ORC, além de CSV clássico
Para análises exploratórias, prototipagem de pipelines e consultas descentralizadas, o DuckDB oferece uma alternativa eficiente a soluções como Spark ou bancos tradicionais.
2. Instalação e primeiros passos com DuckDB
A instalação pode ser feita via pip para Python ou CLI diretamente:
# Instalação via pip
pip install duckdb
# Instalação via CLI (Linux/macOS)
curl -fsSL https://install.duckdb.org | sh
Para iniciar uma sessão interativa:
# Modo CLI
duckdb
# Conectando a um arquivo de banco
duckdb minha_analise.db
Comandos básicos úteis:
# Listar tabelas
SHOW TABLES;
# Importar CSV
.import dados.csv minha_tabela
# Modo de saída
.mode markdown
# Salvar resultados
.output resultados.md
3. Consultando arquivos CSV diretamente
O DuckDB permite consultar arquivos CSV sem importá-los para o banco, usando a função read_csv_auto:
SELECT
categoria,
COUNT(*) AS total_vendas,
ROUND(AVG(valor), 2) AS valor_medio
FROM read_csv_auto('vendas.csv')
WHERE data >= '2024-01-01'
GROUP BY categoria
ORDER BY total_vendas DESC;
Parâmetros importantes para controle de leitura:
SELECT * FROM read_csv_auto(
'dados.csv',
delim=';',
header=true,
encoding='UTF-8',
types={'coluna_data': 'DATE', 'valor': 'DOUBLE'}
);
4. Trabalhando com arquivos Parquet de forma eficiente
Parquet é o formato ideal para análises ad hoc devido à compressão columnar e suporte a pushdown de predicados:
-- Leitura básica
SELECT * FROM read_parquet('vendas.parquet');
-- Consulta com pushdown de predicados (filtros aplicados antes da leitura)
SELECT
ano,
mes,
SUM(receita) AS receita_total
FROM read_parquet('vendas_*.parquet')
WHERE ano >= 2023
GROUP BY ano, mes;
-- Particionamento por data
SELECT * FROM read_parquet('dados/ano=2024/mes=01/*.parquet');
Vantagens do Parquet sobre CSV:
- Compressão columnar: redução de 70-90% no tamanho
- Pushdown de predicados: consultas mais rápidas
- Projeções: leitura seletiva de colunas
- Schema embutido: sem necessidade de inferência
5. Cruzando dados entre CSV e Parquet em uma única consulta
A capacidade de unir fontes heterogêneas é um dos pontos fortes do DuckDB:
WITH vendas AS (
SELECT * FROM read_parquet('vendas.parquet')
),
clientes AS (
SELECT * FROM read_csv_auto('clientes.csv')
)
SELECT
c.nome,
c.cidade,
COUNT(v.id_venda) AS total_compras,
ROUND(SUM(v.valor), 2) AS valor_total
FROM vendas v
JOIN clientes c ON v.id_cliente = c.id
WHERE v.data >= '2024-01-01'
GROUP BY c.nome, c.cidade
ORDER BY valor_total DESC;
Estratégias para schemas divergentes:
-- Tratamento de tipos diferentes
SELECT
CAST(v.id AS VARCHAR) AS id_venda,
c.id_cliente
FROM read_parquet('vendas.parquet') v
JOIN read_csv_auto('clientes.csv') c
ON v.id_cliente = CAST(c.id AS INTEGER);
6. Integração com armazenamento externo (S3, MinIO, HTTP)
DuckDB suporta acesso remoto via extensões:
-- Habilitar extensão HTTP
INSTALL httpfs;
LOAD httpfs;
-- Configurar secrets para S3
CREATE SECRET s3_secret (
TYPE S3,
KEY_ID 'ACCESS_KEY',
SECRET 'SECRET_KEY',
REGION 'us-east-1'
);
-- Consultar dados no S3
SELECT * FROM read_parquet('s3://meu-bucket/dados/*.parquet');
-- Acessar via HTTP
SELECT * FROM read_csv_auto('https://exemplo.com/dados.csv');
Exemplo prático com MinIO:
INSTALL httpfs;
LOAD httpfs;
CREATE SECRET minio_secret (
TYPE S3,
KEY_ID 'minioadmin',
SECRET 'minioadmin',
ENDPOINT 'localhost:9000',
USE_SSL false
);
SELECT
COUNT(*) AS total,
ROUND(AVG(temperatura), 2) AS temp_media
FROM read_parquet('s3://meu-bucket/dados/*.parquet');
7. Otimização de performance e boas práticas
Para extrair o máximo de desempenho:
-- Analisar plano de execução
EXPLAIN ANALYZE
SELECT * FROM read_parquet('grandes_dados.parquet')
WHERE categoria = 'eletronicos';
-- Configurar paralelismo
SET threads = 8;
SET memory_limit = '8GB';
-- Materializar consultas frequentes
CREATE TABLE vendas_resumo AS
SELECT
DATE_TRUNC('month', data) AS mes,
categoria,
SUM(valor) AS total
FROM read_parquet('vendas/*.parquet')
GROUP BY ALL;
Boas práticas para grandes volumes:
- Use Parquet com particionamento inteligente (ex: por data)
- Aplique filtros antes de joins
- Evite
SELECT *em tabelas largas - Monitore o uso de memória com
PRAGMA memory_limit
8. Exportação de resultados e automação de análises
Exportação para múltiplos formatos:
-- Exportar para CSV
COPY (
SELECT * FROM read_parquet('analise.parquet')
) TO 'resultados.csv' (HEADER, DELIMITER ',');
-- Exportar para Parquet
COPY (
SELECT * FROM read_csv_auto('dados.csv')
) TO 'dados.parquet' (FORMAT PARQUET);
-- Exportar para JSON
COPY (
SELECT * FROM read_parquet('vendas.parquet')
) TO 'relatorio.json' (FORMAT JSON);
Automação com Python:
import duckdb
import pandas as pd
conexao = duckdb.connect(':memory:')
# Pipeline ad hoc automatizado
query = """
WITH dados AS (
SELECT * FROM read_csv_auto('vendas_diarias.csv')
)
SELECT
categoria,
SUM(valor) AS faturamento
FROM dados
GROUP BY categoria
ORDER BY faturamento DESC
"""
resultado = conexao.execute(query).fetchdf()
resultado.to_csv('relatorio_diario.csv', index=False)
Combinação com Jupyter Notebook:
# Célula Jupyter
import duckdb
import plotly.express as px
df = duckdb.query("""
SELECT
DATE_TRUNC('month', data) AS mes,
SUM(valor) AS receita
FROM read_parquet('vendas.parquet')
GROUP BY mes
ORDER BY mes
""").df()
fig = px.line(df, x='mes', y='receita', title='Receita Mensal')
fig.show()
Referências
- Documentação Oficial do DuckDB — Guia completo de instalação, sintaxe SQL, extensões e funções para análise de dados.
- DuckDB: An In-Process Analytical Database — Artigo acadêmico original que descreve a arquitetura e design do DuckDB.
- Tutorial: DuckDB + Parquet + S3 — Guia oficial para configurar acesso a buckets S3 e MinIO com DuckDB.
- Analisando Grandes Conjuntos de Dados com DuckDB — Tutorial prático em Python abordando consultas em CSV e Parquet, com exemplos de otimização.
- DuckDB: O Banco de Dados Analítico Embutido — Artigo técnico da InfoQ comparando DuckDB com outras soluções OLAP e demonstrando casos de uso.
- DuckDB vs Pandas para Análise de Dados — Comparação oficial destacando vantagens de performance e escalabilidade do DuckDB sobre bibliotecas Python tradicionais.
- Guia de Performance e Otimização do DuckDB — Documentação com dicas avançadas sobre configuração de memória, paralelismo e profiling de consultas.