Otimização de Consultas e o Problema N+1¶
Otimização começa por evidências: logs lentos, traces, contagem, planos e dados representativos. Intuição sobre objetos não revela índices, linhas examinadas, transferência, locks ou pressão no banco.
Reconhecendo N+1¶
N+1 ocorre quando uma consulta carrega pais e outra consulta é executada para os dados relacionados de cada pai. Costuma se esconder em associações lazy, serialização, mapeamento ou renderização.
Conte statements em teste de integração ou trace. Dados pequenos podem ocultar a latência enquanto a quantidade ainda cresce linearmente.
Estratégia de busca por caso de uso¶
- fetch join carrega relacionamento limitado em uma consulta;
- entity graph explicita associações;
- projeção recupera apenas campos necessários;
- batch ou subselect reduz viagens mantendo lazy loading;
- consulta agregada calcula resumos sem entidades.
Eager generalizado apenas move o problema. Vários relacionamentos to-many multiplicam linhas e memória. Fetch join de coleção interage mal com paginação; em geral, pagine IDs e busque detalhes depois.
Índices e planos¶
O índice deve combinar predicados seletivos e ordem útil, mas custa escrita e armazenamento. Inspecione o plano real com parâmetros realistas. Evite funções em colunas indexadas sem índice de expressão adequado.
Buscar menos linhas e colunas é mais robusto que esconder desperdício com cache. Reduza também o escopo transacional.
Proteção contra regressões¶
- imponha teto de consultas em casos críticos;
- teste linhas suficientes para expor multiplicação;
- inspecione SQL e parâmetros;
- meça cardinalidades e paginação profunda;
- separe tempo do banco e do mapeamento;
- reveja planos após mudanças de esquema ou distribuição.
Consulte as orientações de fetching do Hibernate.