Parquet + DuckDB como alternativa ao SQLite em rede SMB
Salve, devs e devas
Vim trazer mais um relato de problema real aqui da empresa, tentando resolver as coisas dentro das limitações que eu tenho.
Hoje eu não posso:
- Criar um servidor de banco de dados
- Subir um servidor HTTP para todos os usuários acessarem
Por conta disso, todas as soluções que desenvolvo precisam rodar em um servidor de arquivos SMB, onde cada usuário executa seu próprio processo localmente.
Uso o ambiente .NET para desenvolvimento e, alguns anos atrás, comecei usando Microsoft Access. Funcionava… até certo ponto. Com o tempo, a aplicação começou a ficar lenta. Hoje esse banco tem cerca de 18 mil linhas, ocupa 15 MB e, para rodar, precisa instalar o OLE DB / Jet Engine, que o TI frequentemente esquece de instalar, ainda mais porque versões recentes do Office já não vêm mais com o Access.
Tentativa com SQLite
Para fugir dessa dependência, migrei uma outra aplicação para SQLite, principalmente porque queria usar Dapper e também evitar qualquer instalação extra.
Resultados iniciais:
- Banco com 4,8 MB
- Tabelas com 9 mil e 22 mil registros
- Performance bem melhor no uso individual
Porém, surgiram novos problemas quando o banco ficava no compartilhamento SMB:
- Se um usuário já estivesse com o banco aberto, outro usuário demorava muito para iniciar
- Em alguns casos, o primeiro INSERT não era salvo
- Mesmo habilitando WAL, esse problema ainda acontecia ocasionalmente
Há umas semanas postei um outro problema aqui no TabNews, e algumas pessoas sugeriram o DuckDB como alternativa para esse outro cenário.
Descobrindo uma abordagem diferente
Lendo mais sobre o DuckDB, vi que ele também roda in-process, como o SQLite, mas é otimizado para análise (OLAP). Isso me levou a pesquisar mais e, com ajuda de bastante leitura e perguntas para IA, descobri uma abordagem que resolveu um ponto crítico do meu problema:
escritas concorrentes de múltiplos processos em rede SMB.
A solução acabou sendo usar arquivos Parquet.
Eu sei:
“Parquet não é feito para OLTP.”
Para esse cenario onde não existe muitas transações me parece interessante.
A solução adotada
A ideia foi simples:
- Cada INSERT, UPDATE ou soft delete gera um arquivo Parquet
- Nome do arquivo no padrão:
guid_timestamp.parquet - Assim, cada usuário escreve no seu próprio arquivo, sem lock global
Isso gera muitos arquivos pequenos na rede, mas aí entrou uma segunda ideia.
Com a ajuda do meu amigo Cloude, chegamos na seguinte estratégia:
- Ao iniciar a aplicação, se a pasta tiver mais de 100 arquivos, o processo:
- Consolida tudo em um único arquivo Parquet
- Remove os arquivos antigos
- Reduz drasticamente a quantidade de aberturas de arquivo na rede
Benchmark rápido
Fiz um teste simples:
- Criei 2.000 arquivos Parquet
- Consolidei tudo em um único arquivo
Resultados:
- Abertura antes da consolidação (2k de arquivos): ~2130 ms
- Abrir o arquivo consolidado (2k registros): ~24 ms
Pelos testes iniciais, parece bem promissor.
Além disso, como o DuckDB carrega os Parquet em memória (:memory:), e pensando em uma aplicação com mais de uma tabela, percebi que é possível:
- Criar tabelas a partir dos arquivos Parquet
- Trabalhar de forma relacional
- Fazer JOINs normalmente
Contexto da empresa
Aqui na empresa não temos um departamento de desenvolvimento.
Eu acabo atuando como um “automatizador” de processos, usando muito Excel, VBA e agora tentando evoluir isso para aplicações mais estruturadas.
O problema da base de dados é sempre um gargalo, principalmente porque:
- O TI não consegue criar um ambiente de desenvolvimento para a unidade do Brasil
- A matriz até tem equipe de desenvolvimento, mas muitas necessidades são locais e não se aplicam a todas as unidades
Essa abordagem com Parquet + DuckDB parece uma forma viável de, aos poucos, reduzir a dependência do Excel como ERP improvisado
Resolvi compartilhar essa experiência porque a comunidade aqui é sempre muito técnica e tem me ajudado bastante.
Algumas dúvidas
Algumas perguntas que gostaria de ouvir de quem tem mais experiência:
- Alguém aqui já usou Parquet como camada intermediária de escrita nesse estilo (append-only + consolidação)?
- Essa abordagem pode virar uma dor de cabeça a médio/longo prazo?
- Existe algum risco oculto em usar Parquet dessa forma em rede SMB?
- Para esse cenário sem servidor dedicado, existe alguma alternativa melhor que SQLite/DuckDB?
- Em termos de integridade e recuperação de falha, vocês enxergam algum ponto crítico que eu deveria tratar desde já?
Obrigado a todos, sempre lembrando qualquer contribuição é muito bem vinda.