~/beer-and-code
~ / eventos / workshop-importacao-de-dados-com-laravel $ _
Workshop Encerrado

Workshop: Importação de Dados com Laravel

Workshop prático de 2025-03-20, comandado por Daniel Sampaio e Virgílio (Virgo), sobre como importar grandes volumes de dados (CSV/Excel/JSON/XML) no Laravel sem estourar memória, sem timeout e sem travar o banco. O ponto de partida foi provocativo: rebater a...

Ficha do evento
formato workshop
quando 20 Mar 2025
horário 19h às 22h
status encerrado

Workshop tenso e didático, gravado numa quinta à noite, puxado pelo desafio real que motivou a aula: o Daniel sempre recorria a Python/R para tratar grandes volumes de dados no PHP, e o Virgo topou provar que dá para fazer isso direito dentro do próprio Laravel — sem gambiarra, sem aumentar memory_limit no php.ini feito herói. O exemplo usado foi realista: uma base de customers com relacionamentos em cascata (property, person/titular, address, cônjuge), simulando listas de clientes de incorporadora geradas via script Python até 10 milhões de linhas.

Destaques

  • Baseline (import 01): Collection + str_getcsv + Model::create() linha a linha — funciona até uns milhares, mas gera 5 queries por linha (500 queries para 100 clientes) e trava com memória em CSVs grandes; ficou explícito que Laravel Excel e Simple Excel (Spatie) não seguram acima de ~1 milhão de linhas por dependerem de Collection/LazyCollection internamente.
  • Bulk insert (import 02): trocar create() linha a linha por inserts em lote por tabela reduz drasticamente as queries (de 500 para 7 em 1k clientes), mas ainda carrega o arquivo inteiro na memória e esbarra no limite de placeholders de prepared statement do MySQL por volta de 10k linhas.
  • Chunk (import 03): quebrar a Collection em pedaços de 1000 com ->chunk() resolve o limite de placeholders e já roda 10k em ~2s, mas ainda carrega tudo em memória de uma vez (quebra perto de 100k).
  • LazyCollection/generators (import 04/05): uso de LazyCollection (baseada em yield/generators do PHP, disponível desde o Laravel 6) para ler e processar linha a linha sem acumular tudo em memória; combinado com chunk, chega a 96k antes de estourar — porque mesmo processando aos poucos, ainda instancia muitos Models e objetos Carbon, que pesam mais que strings.
  • PDO cru + prepared statements manuais (import 06): abandonar Eloquent/Model/Carbon dentro do loop e montar o INSERT na mão com placeholders (?) e PDOStatement::execute() — troca o custo de "objeto" por custo de "string", derruba memória de ~22MB para menos de 1MB em 10k linhas e sustenta 1 milhão de linhas em ~2min50s com 5 mil queries.
  • Concorrência com a facade Concurrency (Laravel 12, ainda beta): divide o arquivo em N processos paralelos (10 no exemplo, calibrado pela RAM/CPU disponível, cada processo com sua própria conexão via DB::reconnect()), derrubando o tempo de 1 milhão de linhas de ~2min50s para ~1min40s — só vale quando as linhas são independentes entre si (sem sequência lógica entre elas).
  • Validação em lote sem N+1: regras normais do Validator do Laravel linha a linha, mas a checagem de unicidade de e-mail é feita à parte, acumulando e-mails do chunk inteiro e disparando um único whereIn no banco, em vez de uma query por linha.
  • Pipeline mais próximo do real: upload salvo em disco (S3/local), Bus::chain() encadeando fila de validação → fila de importação, tudo rodando via Horizon + Redis (justificado pela concorrência de recursos com o próprio banco), e broadcast de evento (ShouldBroadcast) via Reverb avisando o front quando a importação termina.

Profundidade técnica

A aula foi fundo em internals de PHP/Laravel: diferenciou objeto vs string em termos de alocação de memória (por que Model + Carbon custam mais que strings puras), explicou generators (yield) por trás do LazyCollection, mostrou na prática o limite de placeholders de prepared statement do MySQL e por que aumentar esse limite é trade-off (mais tempo de lock e escrita de índice), e discutiu trade-offs de begin transaction (quando faz sentido — chamadas externas tipo CRM/API — e quando é desnecessário em import simples). Também tratou armadilhas do mundo real: CSV sujo vindo de usuário, decisão de negócio entre abortar a importação inteira (fail-fast) ou logar erro por linha e seguir, por que LOCAL DATA INFILE do MySQL é rápido mas geralmente inviável em RDS gerenciado, e quando concorrência vira problema (deadlock em cenários de update/upsert). Ficou claro o recado central: otimizar código é a primeira instância antes de jogar dinheiro em mais servidor, réplica de banco ou infraestrutura.

Faça parte do Clã

Se você quer estar na sala quando esse tipo de aula acontece — com banco de dados populado ao vivo, código real sendo otimizado passo a passo e a galera tirando dúvida em tempo real — é isso que rola toda semana dentro do Clã Beer and Code. Além do acesso gravado a workshops como este, tem mentoria técnica direta, uma trilha de especialização em Laravel que vai muito além de model/controller/migration, e uma comunidade que puxa todo mundo para cima. Se você já apanhou de importação grande em produção, é hora de aprender a resolver isso de vez — sem depender de trocar de linguagem.

▪ Clã Beer and Code
Faça parte do Clã. Construa o que importa.

Engenharia de IA virou profissão, e se aprende construindo, não assistindo. O Clã Beer and Code é o ambiente onde isso acontece ao vivo, toda semana: RAG, agentes, observabilidade e LLMOps em projetos reais, ao lado de quem já está em produção. É pago, é assinatura, e é exatamente o ambiente que estes encontros dão uma amostra.

Entrar no Clã
tocando