Por que o sistema fica lento e o que resolve de verdade
Na maioria dos casos a lentidão vem do banco de dados, não do servidor. Veja como identificar a causa real antes de gastar dinheiro trocando de máquina.
Em sistema de empresa, a lentidão quase sempre vem de consulta ao banco sem índice adequado ou de muitas consultas pequenas por tela. Trocar por um servidor maior costuma comprar alguns meses e esconder o problema. Meça primeiro onde o tempo é gasto, depois corrija a causa.
Quando um sistema de empresa fica lento, a causa está no banco de dados em algo como oito de cada dez casos. Consulta sem índice adequado, muitas consultas pequenas por tela, ou tabela que cresceu e ninguém revisou. Comprar um servidor maior costuma comprar alguns meses de alívio e esconder o problema real, que volta maior. O caminho correto é medir onde o tempo é gasto antes de gastar dinheiro.
Primeiro: descubra onde o tempo está
Sem medição, otimização é chute. Três medições resolvem quase tudo:
Tempo por requisição, no servidor. Quanto cada endpoint demora, no percentil 95, não na média. A média esconde exatamente os casos que geram reclamação.
Tempo gasto no banco dentro de cada requisição. Se dos 3 segundos de uma tela, 2,7 são banco, não adianta olhar para o código de renderização.
Consultas mais custosas por tempo acumulado. No PostgreSQL, pg_stat_statements ordenado por total_exec_time. No MySQL, o log de consultas lentas. O critério é tempo total, não tempo unitário.
Essa terceira medição costuma entregar o culpado em minutos. E a resposta frequentemente surpreende: não é o relatório pesado que todo mundo culpa, é a consulta de 40 ms que roda 300 vezes por página.
Causa 1: falta de índice
É a campeã. Sem índice, o banco lê a tabela inteira para encontrar as linhas que interessam. Com 5 mil registros ninguém percebe. Com 5 milhões, a tela trava.
Como confirmar: rode EXPLAIN ANALYZE na consulta. Se aparecer Seq Scan em tabela grande com filtro seletivo, achou.
Regras práticas:
- Índice em toda chave estrangeira. Muitos frameworks criam a restrição e esquecem o índice.
- Índice composto na ordem das colunas mais filtradas, geralmente
(tenant_id, data)ou(status, criado_em). - Índice parcial quando você só consulta um subconjunto:
WHERE ativo = true. Fica menor e mais rápido. - Não crie índice em tudo. Cada índice torna a escrita mais lenta e ocupa espaço. Índice nunca usado é só custo, o banco informa quais nunca foram acessados.
Índice certo transforma segundos em milissegundos. É a melhoria com maior retorno por hora de trabalho em sistema de empresa.
Causa 2: N+1, muitas consultas pequenas
A tela lista 100 pedidos. Para cada pedido, o código busca o nome do cliente. São 101 consultas em vez de uma. Nenhuma delas aparece como lenta no log, e a tela leva 4 segundos.
Isso acontece por padrão em quase todo ORM quando ninguém pede o carregamento antecipado. A correção é declarar as relações que a tela precisa numa única consulta (JOIN ou carregamento em lote).
Como detectar: conte as consultas por requisição. Se uma tela dispara mais de 20 consultas, provavelmente há N+1 ali.
Causa 3: trazer dados demais
Três padrões comuns:
SELECT *em tabela larga quando a tela usa quatro colunas. Trafega e serializa o que ninguém vai ler.- Listagem sem paginação. Funcionou por dois anos com 800 registros e quebrou ao chegar em 80 mil.
- Filtro aplicado na aplicação. Buscar tudo e filtrar em memória descarta na aplicação o trabalho que o banco faria com índice.
Causa 4: consulta mal escrita
Alguns padrões impedem o uso de índice mesmo quando ele existe:
| Padrão problemático | Alternativa |
|---|---|
WHERE YEAR(data) = 2026 |
WHERE data >= '2026-01-01' AND data < '2027-01-01' |
WHERE UPPER(nome) = 'ANA' |
Índice em expressão, ou coluna normalizada |
LIKE '%texto%' |
Busca textual nativa ou índice de trigrama |
| Subconsulta correlacionada por linha | JOIN ou agregação em uma passagem |
OFFSET 50000 em paginação |
Paginação por cursor, usando a última chave lida |
Quando cache é a resposta certa
Cache resolve leitura repetida de dado que muda pouco: tabelas de configuração, listas de opções, resultado de relatório pesado, resposta de API externa.
Cache não resolve consulta mal indexada, só adia. E introduz um problema novo: invalidação. Antes de adicionar cache, responda o que acontece quando o dado muda e quem limpa a entrada antiga.
Ordem de preferência: primeiro corrigir a consulta, depois cachear o que sobrar.
Quando o problema é mesmo infraestrutura
Existem casos em que a máquina é a limitação real. Os sinais:
- CPU acima de 80% de forma sustentada, com as consultas já otimizadas
- Memória insuficiente para o cache do banco, gerando leitura de disco constante
- Disco lento, banco em disco mecânico ou volume de rede sem IOPS suficiente
- Pool de conexões esgotado, com requisições esperando por conexão livre
- Um único processo de aplicação atendendo requisições concorrentes
Nesses casos, aumentar recurso é a decisão correta. A diferença é que agora você sabe por quê, e o ganho é previsível.
Roteiro em ordem de custo-benefício
- Medir: tempo por endpoint, tempo em banco, consultas mais custosas
- Rodar
EXPLAIN ANALYZEnas três piores e criar os índices faltantes - Contar consultas por requisição e eliminar os N+1
- Paginar listagens e reduzir colunas trazidas
- Reescrever as consultas que anulam índice
- Cachear o que é caro e muda pouco
- Só então revisar hardware, com dados de saturação na mão
Os cinco primeiros passos são horas de trabalho e não têm custo mensal. O último tem custo recorrente e não conserta nada, apenas dá mais fôlego para o mesmo problema.
Evitar que volte
Lentidão reaparece porque a base cresce. Duas práticas mantêm o problema sob controle: medir o tempo de resposta em produção continuamente, com alerta quando o percentil 95 passa de um limite, e testar as telas críticas com volume realista antes de subir, não com as vinte linhas do ambiente de desenvolvimento. A maioria das consultas lentas em produção passou sem alarde no ambiente de teste porque lá a tabela tinha cem registros.
Perguntas frequentes
Aumentar o servidor resolve a lentidão?
Normalmente adia. Se a causa é consulta sem índice, dobrar a CPU corta o tempo pela metade enquanto o problema cresce junto com a base. Um índice bem escolhido costuma cortar de segundos para milissegundos, sem custo mensal. Hardware é a resposta certa quando a medição aponta saturação real.
Como descobrir qual consulta está lenta?
Ative o log de consultas lentas do banco e liste as mais custosas por tempo total. No PostgreSQL, a extensão pg_stat_statements ordena por tempo acumulado. Uma consulta de 40 ms executada 300 vezes por tela pesa mais que uma de 2 segundos executada uma vez por dia.
O que é o problema N+1?
É quando a aplicação busca uma lista com uma consulta e depois faz uma consulta adicional para cada item da lista. Uma tela com 100 registros dispara 101 consultas. Some cada uma delas com o tempo de ida e volta ao banco e a tela leva segundos sem que nenhuma consulta pareça lenta.
Tem um processo que consome o time?
Me conta como funciona hoje. Se der para automatizar, eu te digo por onde começar — a conversa de diagnóstico não é cobrada.
Natiam Gabriel é AI Engineer & Full-Stack Developer e fundador da Retti Tech, estúdio de desenvolvimento de software que atende empresas em todo o Brasil. Constrói sistemas web sob medida, automações e integrações, com ou sem inteligência artificial, do levantamento de requisitos até a operação em produção. Mais de 20 empresas usam em produção os sistemas que desenvolveu.