Lentidão de banco de dados quase nunca chega como problema técnico. Chega como reclamação de negócio: o relatório não abre, o pedido demora a confirmar, o fechamento do mês atrasa. A reação mais comum é pedir mais CPU, mais memória ou abrir um chamado genérico de "banco lento". Em PostgreSQL e MySQL, esse caminho costuma custar caro e resolver pouco, porque a causa geralmente está em uma consulta, em um índice mal escolhido ou em estatísticas desatualizadas.
O plano de execução mostra o que o monitor de servidor não mostra
Um gráfico de CPU alta diz que algo consome recurso, não diz o quê. O plano de execução responde a pergunta certa: onde o tempo foi gasto. Nas duas engines, o comando é parecido, mas a leitura muda.
- No PostgreSQL,
EXPLAIN (ANALYZE, BUFFERS)entrega tempo real por nó, linhas estimadas contra linhas efetivas e leitura de cache. Uma diferença grande entre estimado e real é sinal clássico de estatística velha ou de correlação entre colunas que o planejador não enxerga. - No MySQL 8,
EXPLAIN ANALYZEfaz o mesmo papel. Em versões anteriores, a leitura sai doEXPLAIN FORMAT=JSONcombinado com o slow query log. Sem esse log ligado, você diagnostica por relato de usuário, o que não é diagnóstico. - Manutenção pesa diferente em cada uma. No PostgreSQL, autovacuum atrasado gera bloat e planos ruins. No MySQL, estatísticas do InnoDB e fragmentação de tabelas pedem acompanhamento próprio.
- Recursos de índice não são portáveis. O PostgreSQL tem índice parcial e índice por expressão. O MySQL 8 resolve parte dos casos com índice funcional e coluna gerada. Copiar a solução de uma engine para a outra costuma não funcionar.
O relatório que travava o fechamento de uma distribuidora
Uma distribuidora de material de construção rodava o ERP em MySQL e mantinha uma réplica PostgreSQL para relatórios gerenciais. A curva ABC de clientes, que antes rodava à noite, passou a ser pedida durante o dia. O relatório demorava e, quando rodava junto com o fechamento, deixava o sistema lento para o time de faturamento.
A primeira proposta foi aumentar a réplica. Antes disso, a leitura do plano mostrou varredura completa na tabela de itens de pedido: a consulta aplicava uma função sobre a coluna de data no filtro, o que impedia o uso do índice existente. Havia ainda um segundo problema, mais silencioso: a rotina de atualização de estatísticas tinha ficado para trás depois de uma migração, e o planejador trabalhava com estimativas irreais.
A correção foi de baixo custo: reescrever o filtro para comparar a coluna diretamente, criar um índice composto adequado ao relatório e recolocar a atualização de estatísticas na rotina de manutenção. Nenhum servidor novo entrou. O ganho veio de diagnóstico, não de hardware.
Na prática
Para quem mantém software em produção, o hábito importa mais que a ferramenta:
- Ligue o slow query log com um limite coerente com a expectativa do negócio e revise os registros toda semana, não apenas em incidente.
- Peça o plano de execução antes de aprovar compra de servidor. Sem ele, a decisão de capacidade é aposta.
- Trate estatísticas e vacuum como parte do deploy, com rotina monitorada. Planejador desatualizado gera plano errado em consulta correta.
- Audite índices criados por urgência. Índice duplicado ou sem uso ocupa espaço e cobra preço em toda escrita.
- Depois de qualquer ajuste, meça de novo com a mesma consulta e a mesma massa de dados. Sem comparação, não há prova de melhora.
Performance de banco em PostgreSQL ou MySQL é trabalho de investigação, e não de tentativa e erro. O tempo investido em ler o plano costuma ser menor que o custo de escalar um problema que estava na consulta.