O gargalo raramente está onde a equipe supõe
Quando um sistema fica lento, a primeira reação é pedir mais hardware ou considerar a troca de banco de dados. Na prática, a maior parte da lentidão percebida em PostgreSQL e MySQL nasce de consultas mal escritas, índices ausentes ou uma modelagem que não acompanhou o crescimento do negócio. Antes de decidir por infraestrutura ou migração, o caminho é medir: identificar as consultas mais custosas, ler o plano de execução (EXPLAIN ANALYZE no PostgreSQL, EXPLAIN no MySQL) e descobrir se o problema é volume de leitura, custo de escrita ou contenção por concorrência.
Vale separar três situações que costumam ser tratadas como uma só: uma consulta específica que ficou lenta, uma disputa por locks entre transações que se cruzam e uma rotina analítica pesada rodando no mesmo horário do tráfego transacional. Cada uma pede uma resposta distinta, e confundir as três leva a otimizações que não resolvem nada.
Modelagem é decisão de custo, não só de desenho
A modelagem define a performance antes de a primeira consulta existir. Chaves naturais longas replicadas como chave estrangeira em várias tabelas inflam índices e encarecem cada join. Colunas de texto para armazenar códigos curtos e datas guardadas como texto impedem o otimizador de usar estatísticas de forma eficiente. Normalização em excesso cria joins desnecessários nos caminhos de leitura, enquanto desnormalização sem critério abre espaço para inconsistência. O ponto de equilíbrio vem do padrão de acesso: o que é lido junto deve ficar perto; o que muda em transações separadas deve viver separado.
Um caso concreto: uma distribuidora de autopeças com operação em três estados tinha um relatório de curva ABC que travava o comercial toda segunda-feira pela manhã. A consulta filtrava por data na tabela de pedidos, mas o índice existia apenas na coluna de vínculo com os itens, e o banco varria a tabela inteira de itens a cada execução. A correção não envolveu trocar de banco: entrou um índice composto na ordem em que o filtro realmente acontece, a consulta foi reescrita com join explícito e o agregado passou a ser materializado em uma rotina noturna. O relatório deixou de competir com o atendimento, e a equipe parou de tratar "banco lento" como causa raiz.
Índices, planos e o roteiro de diagnóstico
Um roteiro que funciona nos dois bancos:
- Ative e leia o log de consultas lentas (slow query log no MySQL, log_min_duration_statement no PostgreSQL). Sem isso, a discussão vira opinião.
- Rode o plano de execução da consulta problemática com dados reais, não com uma tabela de teste vazia.
- Verifique se há varredura completa em tabela grande, se o índice é realmente usado e se a ordem das colunas no índice corresponde ao filtro praticado pelo sistema.
- Confira estatísticas atualizadas (ANALYZE no PostgreSQL, ANALYZE TABLE no MySQL). Estatística velha faz o otimizador escolher o caminho errado mesmo com o índice correto.
- Só então considere cache, particionamento, réplica de leitura ou troca de engine.
- Índice composto resolve quando o filtro combina colunas; um índice isolado por coluna nem sempre é aproveitado.
- Índices parciais no PostgreSQL e filtros por prefixo no MySQL reduzem o tamanho do índice quando o domínio é restrito.
- Criação de índice em produção exige cuidado com bloqueio de escrita: CREATE INDEX CONCURRENTLY no PostgreSQL evita travar a tabela, e no MySQL vale usar as opções de DDL online do InnoDB quando aplicável.
Na prática
Quem mantém software em produção precisa tratar performance de banco como rotina, não como incidente. Na prática:
- Inclua a leitura do plano de execução no ciclo de revisão das consultas novas, antes do deploy.
- Monitore latência por consulta e revise o comportamento após cada mudança relevante no volume de dados.
- Passe toda migração de schema por versionamento, com atenção a tipos e índices criados.
- Mantenha rotinas de atualização de estatísticas e de limpeza de versões antigas (VACUUM no PostgreSQL e o ciclo de purge no InnoDB).
- Documente cada índice e a razão de sua existência. Índice duplicado ou sem uso apenas encarece a escrita.
PostgreSQL e MySQL sustentam bem sistemas que crescem quando a modelagem acompanha o domínio e as consultas são medidas. Trocar de banco deve ser a última hipótese, sempre depois de entender o plano de execução.