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 ANALYZE faz o mesmo papel. Em versões anteriores, a leitura sai do EXPLAIN FORMAT=JSON combinado 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:

  1. 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.
  2. Peça o plano de execução antes de aprovar compra de servidor. Sem ele, a decisão de capacidade é aposta.
  3. Trate estatísticas e vacuum como parte do deploy, com rotina monitorada. Planejador desatualizado gera plano errado em consulta correta.
  4. Audite índices criados por urgência. Índice duplicado ou sem uso ocupa espaço e cobra preço em toda escrita.
  5. 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.