Posted on: January 02, 2026 12:23 AM
Posted by: Renato
Categories: Laravel
Views: 138
Laravel: Upsert e Performance em Massa no Banco de Dados
Quando falamos de performance em aplicações Laravel, muitos desenvolvedores pensam imediatamente em cache. Mas, na prática, um dos maiores gargalos está em como interagimos com o banco de dados — especialmente em operações de sincronização em massa.
O cenário comum (e problemático)
É muito comum encontrar códigos como este ao sincronizar dados vindos de uma API externa, CSV ou integração entre sistemas:
foreach ($users as $user) {User::updateOrCreate(['email' => $user['email']],['name' => $user['name']]);}
À primeira vista, o código parece correto, legível e “laravelizado”.
Porém, ele esconde um problema sério de performance.
O problema real
Para cada registro, o Laravel executa:
-
Um
SELECTpara verificar se o registro existe -
Um
INSERTouUPDATE
Ou seja:
-
1.000 registros
-
2.000 queries no banco
-
Alta latência
-
Consumo excessivo de CPU e I/O
-
Possível queda de performance do servidor
Em ambientes com PostgreSQL ou MySQL sob carga, isso pode facilmente levar a timeouts, lentidão geral da aplicação e filas travadas.
A solução: upsert
A partir do Laravel 8, temos o método upsert, projetado exatamente para esse tipo de cenário.
Ele permite inserir ou atualizar múltiplos registros em uma única query.
User::upsert($users,['email'], // Coluna única para verificação['name'] // Colunas que serão atualizadas se já existir);
O que acontece aqui?
-
O Laravel gera uma única query SQL
-
O banco decide se deve inserir ou atualizar
-
Tudo acontece de forma atômica e extremamente eficiente
No PostgreSQL, por exemplo, isso vira algo próximo de:
INSERT INTO users (...)ON CONFLICT (email)DO UPDATE SET name = EXCLUDED.name;
Resultado prático
Em testes reais:
-
❌ Abordagem antiga (
updateOrCreateem loop): ~2 minutos -
✅ Com
upsert: ~200 milissegundos
Isso é uma melhoria de ordem de magnitude, não apenas “otimização fina”.
Quando usar upsert?
Use upsert sempre que:
-
Estiver lidando com grandes volumes de dados
-
Sincronizar informações externas
-
Importar CSVs
-
Atualizar tabelas de apoio, catálogos ou dados de referência
-
Executar jobs ou commands agendados
Evite updateOrCreate em loops para operações em massa.
Conclusão
Performance não é apenas cache, index ou hardware.
🚀 Performance começa na forma como você conversa com o banco de dados.
Se o banco consegue resolver em uma query, não force o Laravel a resolver em mil.
Inserts de Alta Performance (Upsert)
Pare de executar 1.000 queries para salvar 1.000 registros.
Vejo com muita frequência esse tipo de código quando desenvolvedores estão sincronizando dados vindos de uma API ou de um CSV:
foreach ($users as $user) {User::updateOrCreate(['email' => $user['email']],['name' => $user['name']]);}
O Problema
Se você tiver 1.000 usuários, esse código executa 2.000 queries no banco de dados:
-
1
SELECT -
1
INSERTouUPDATE -
Para cada registro
Resultado?
👉 Seu servidor vai sofrer (choke).
A Solução
O Laravel 8+ introduziu o método upsert, que faz tudo em uma única query.
User::upsert($users,['email'], // Coluna única para verificação['name'] // Colunas que serão atualizadas se o registro existir);
O Resultado
-
Forma antiga: 2 minutos
-
Nova forma (upsert): 200 milissegundos
Conclusão
Performance não é só sobre cache.
🚀 É sobre como você conversa com o seu banco de dados.
SLOW SYNC 🐢
foreach ($rows as $row) {// Runs 1000 times...User::updateOrCreate(...);}
🐌 10%
1,000+ Queries. Server Chokes.
FAST UPSERT 🚀
// Runs 1 time!User::upsert($rows, ...);
✅
1 Single Query. Instant Sync.
Donate to Site
Renato
Developer