Por que extraí dados do SQL Server para Parquet
Trabalho com dados em SQL Server e precisava alimentar ferramentas analíticas sem sobrecarregar o banco transacional. Depois de tentar conexão direta e CSV, cheguei no Apache Parquet — um formato aberto, colunar e comprimido que se tornou o padrão de fato para dados analíticos.
Participe do nosso grupo de Estudos!!! Cadastre-se em https://gubigdata.com.br/grupo-de-estudos/
O problema: SQL Server como fonte de analytics
O SQL Server é excelente como banco transacional — ACID, integridade referencial, stored procedures. Mas quando comecei a rodar análises sobre grandes volumes de dados, encontrei limitações:
- Formato orientado a linhas — para ler uma coluna específica de 1 milhão de registros, ele precisa varrer todas as linhas e todas as colunas
- Licenciamento — a versão Express tem limite de 10 GB por banco e 1 GB de RAM
- Concorrência — minhas queries analíticas pesadas competiam com o sistema transacional em produção
- Portabilidade — os dados ficavam presos no ecossistema Microsoft
A pergunta que me fiz não foi “como conectar minha ferramenta ao SQL Server”, mas sim: “como libertar meus dados para que qualquer ferramenta possa consumi-los?”
Por que Parquet e não CSV, JSON ou conexão direta?
CSV: simples mas limitado
CSV não tem tipos. Um campo 123.45 é texto — cabe a quem lê decidir se é string, float ou decimal. Nos meus dados financeiros, essa ambiguidade era inaceitável. Além disso, CSV não comprime bem e não suporta NULLs nativos (é "" ou "NULL"?).
JSON: flexível mas pesado
JSON carrega metadados em cada registro (nome do campo repetido em toda linha). Um arquivo JSON com 1 milhão de registros ficava facilmente 5x maior que o equivalente em Parquet.
Conexão direta: prática mas frágil
Em produção, as queries pesadas travavam o sistema transacional, o SQL Server virava gargalo, e qualquer manutenção no banco derrubava meus dashboards.
Parquet: o melhor dos mundos
O Apache Parquet resolveu todos esses problemas:
- Formato colunar — se preciso de 3 colunas de uma tabela com 40, ele lê apenas essas 3. Isso mudou completamente a performance das minhas queries analíticas
- Schema tipado embutido — cada arquivo carrega a definição dos tipos (string, decimal com precisão, date, boolean). Sem ambiguidade
- Compressão eficiente — dados colunares comprimem muito melhor que dados em linha. Valores repetidos na mesma coluna (como status, datas, flags) comprimem drasticamente
- NULLs nativos — NULL é NULL, não string vazia
- Portável — qualquer ferramenta moderna lê Parquet nativamente
- Imutável — uma vez gerado, o arquivo é uma foto consistente dos dados. Sem surpresas de concorrência
Quem lê Parquet?
Praticamente tudo no ecossistema de dados moderno:
- ClickHouse — lê Parquet diretamente com
SELECT * FROM file('dados.parquet') - DuckDB — banco analítico embarcado, ideal para explorar Parquet no notebook ou terminal
- chDB — engine do ClickHouse embarcada em Python, sem servidor
- Apache Spark — Parquet é o formato nativo do Spark
- Pandas / Polars —
pd.read_parquet()é mais rápido queread_csv()e preserva tipos - Power BI / Tableau — suportam Parquet como fonte de dados
- AWS Athena / Google BigQuery — consulta Parquet diretamente no storage (S3/GCS)
Ou seja: ao exportar para Parquet, desacopla os dados do SQL Server e os torna consumíveis por qualquer ferramenta, em qualquer cloud, em qualquer linguagem.
As ferramentas
pyodbc — a ponte com o SQL Server
O pyodbc é o driver Python para conexões ODBC. Ele se conecta ao SQL Server usando o ODBC Driver 17 ou 18 da Microsoft e retorna os dados em tipos Python nativos. Suporta autenticação Windows (quando o script roda na mesma máquina) e autenticação SQL (user/password para conexões remotas).
pandas — leitura em chunks
O pandas tem uma funcionalidade essencial para tabelas grandes: o parâmetro chunksize no pd.read_sql(). Em vez de carregar 800 mil linhas na memória de uma vez, leio em batches de 50 mil. O uso de memória fica constante independente do tamanho da tabela.
PyArrow — escrita Parquet com tipos precisos
O PyArrow é a implementação Python do Apache Arrow. Ele escreve arquivos Parquet com schemas tipados — defino exatamente o tipo de cada coluna. Isso é crítico para dados financeiros: um decimal(26,2) do SQL Server precisa virar decimal128(26,2) no Parquet, não float64 que perde centavos.
O ponto crítico: mapeamento de tipos
A parte mais importante da extração não foi a conexão nem a leitura — foi garantir que os tipos fossem preservados corretamente. Um erro aqui corrompe os dados silenciosamente.
Os casos que merecem atenção:
- decimal → decimal128 — nunca converta para float. O número
0.10não tem representação exata em float64. Para valores financeiros, a perda de centavos é inaceitável - uniqueidentifier → string — UUIDs do SQL Server são armazenados como 16 bytes binários. No Parquet, a representação mais portável é string lowercase (
"a1b2c3d4-...") - nvarchar(MAX) → string UTF-8 — o SQL Server armazena nvarchar como UTF-16. O driver ODBC converte para UTF-8 na leitura, mas vale validar caracteres especiais
- bit → boolean — parece trivial, mas se você deixar o PyArrow inferir, ele pode tratar como inteiro
- NULLs — o Parquet suporta NULLs nativos em qualquer tipo. Não converta para string vazia ou zero
A solução que foi definir schemas PyArrow explícitos para cada tabela, sem depender de inferência automática. É mais trabalho inicial, mas elimina surpresas.
SQL Server Express
Meu SQL Server era a versão Express, e antes de conseguir conectar remotamente precisei configurar várias coisas:
- TCP/IP vem desabilitado — o Express só aceita conexões locais via shared memory. Precisei habilitar TCP/IP no Configuration Manager e definir a porta 1433
- Autenticação só Windows — para conectar do Linux/WSL2, precisei habilitar o modo misto (SQL + Windows Auth)
- Firewall bloqueia — o script rodava no WSL2, e precisei criar regra no firewall do Windows para a porta 1433
- Instância nomeada — o Express usa
localhost\SQLEXPRESSem vez da porta padrão. Sem o SQL Browser rodando, precisei configurar porta fixa
Documentei todos os passos de configuração no repositório do projeto do github AQUI.
Resultado
Teste com 6 tabelas e 1,3 milhão de registros:
- Tempo de extração: 28 segundos
- Tamanho em Parquet: 250 MB (com compressão Snappy)
- Memória: constante em ~200 MB (leitura em chunks de 50k linhas)
- Tipos preservados: decimal com precisão exata, UUIDs, datas, booleanos
A partir desses Parquet, os dados podem ser carregados no ClickHouse, consultados com DuckDB, ou consumidos por qualquer ferramenta analítica — sem depender do SQL Server estar online.
Quando usar essa abordagem
Faz sentido quando:
- Você precisa alimentar ferramentas analíticas sem sobrecarregar o SQL Server
- Está migrando para uma stack de dados moderna (ClickHouse, DuckDB, Spark, cloud)
- Precisa de snapshots consistentes dos dados para auditoria ou reprocessamento
- Quer desacoplar a camada de analytics do banco transacional
- Precisa compartilhar datasets com times que não têm acesso ao SQL Server
Não faz sentido quando:
- Você precisa de dados em tempo real (Parquet é batch, não streaming)
- O volume é pequeno (menos de 10 mil linhas) e a consulta é ocasional
- O SQL Server já atende bem suas necessidades analíticas
Cadastre-se no nosso grupo de estudos!
Código e documentação
O script completo, com schemas de exemplo, documentação de setup do SQL Server Express, e instruções de uso, está disponível no GitHub. O README inclui um guia de como adaptar para suas próprias tabelas.
Alessandro Binhara
