Um banco de dados que se recusa a fazer o óbvio

Imagine que você pergunte ao seu banco de dados: "quais empresas japonesas lançaram mais filmes nos anos 2000?" A resposta é fácil de entender, mas o caminho que o banco percorre até ela não é. Dependendo da ordem em que ele decide juntar as tabelas, ele pode fazer quatro vezes mais trabalho do que precisaria. É como entregar encomendas numa cidade: o custo final depende de quantos armazéns você visita antes de chegar ao destino.

Quem decide esse caminho é o otimizador de consultas — um pedaço do banco de dados que existe para escolher o plano de execução mais barato antes de rodar qualquer coisa. No PostgreSQL, esse componente tem décadas de engenharia por trás. E, mesmo assim, ele erra com frequência maior do que a maioria dos desenvolvedores imagina.

Foi esse erro que o engenheiro Rohan Bansal decidiu atacar — usando um modelo de linguagem de 4 bilhões de parâmetros, treinado por reforço, rodando em cima de duas GPUs alugadas e quatro contêineres de PostgreSQL no escritório dele. O resultado, publicado em 16 de setembro de 2026: planos de consulta até 81% mais rápidos do que os planos que o próprio PostgreSQL escolheria sozinho.

Por que otimizar consulta é tão difícil

A tarefa mais espinhosa do otimizador se chama ordenação de junções (join ordering). Quando você junta três tabelas, o banco pode combinar as duas primeiras e depois juntar o resultado com a terceira, ou começar pelas duas últimas. Cada junção ainda pode usar diferentes algoritmos — hash join, merge join ou nested loop — e cada tabela pode ser lida de formas distintas: sequencialmente, por índice, por índice cobrindo ou por bitmap.

Isso vira uma explosão combinatória. Para uma consulta com três tabelas, Bansal calculou 4.608 planos possíveis. Com cinco tabelas, 33 milhões. Com doze tabelas — algo comum em relatórios analíticos de verdade —, o número chega a 7,2 × 10²², mais do que o número de grãos de areia da Terra. Não é falta de esforço dos engenheiros: ordenar junções é um problema NP-difícil, formalizado ainda em 1984 pelos pesquisadores Ibaraki e Kameda.

Ele estima, não conta

Aqui está o ponto central. Seria razoável esperar que o banco simplesmente contasse quantas linhas cada junção produz e escolhesse o plano com menos linhas. Só que ele não pode contar nada antes de executar — contar seria executar a consulta inteira, e aí o otimizador perderia sua razão de existir.

Em vez disso, o PostgreSQL estima. Ele consulta estatísticas das colunas, com valores mais frequentes e histogramas, e ao juntar tabelas assume que a distribuição de uma coluna se repete na outra. É a chamada premissa de distribuição uniforme. Na maior parte do tempo funciona. Quando falha, falha feio: se 5% das empresas de cinema são japonesas, mas essas mesmas 5% produziram 50% dos filmes, a estimativa continua em 5% enquanto a realidade explode. Uma estimativa ruim numa junção inicial contamina todas as outras que vêm depois.

Gráfico do paper RELOAD mostrando a baixa eficiência de otimizadores aprendidos por reforço
Figura 1(b) do paper RELOAD (arXiv 2604.14725): a baixa eficiência de um otimizador de consultas "aprendido" por reforço no Join Order Benchmark — Expert é o PostgreSQL, RL é o Balsa. Modelos têm dificuldade para convergir rápido nesse problema.

Como se empurra um PostgreSQL

Existe uma saída elegante: a extensão pg_hint_plan, que permite mandar instruções ao banco como se fossem comentários no SQL. Um comentário começando com /*+ é ignorado pelo PostgreSQL, mas lido pela extensão, que força decisões específicas: usar hash join entre estas tabelas, ler aquela tabela sequencialmente, juntar nesta ordem. É esse encaixe que abre a porta para o experimento: se existe uma linguagem para sugerir planos, talvez um modelo pequeno consiga aprender a usá-la melhor que as heurísticas internas do banco.

Um modelo de 4 bilhões no volante

Bansal não tentou reescrever o otimizador — o que seria lutar contra décadas de pesquisa em estimativa de cardinalidade. Ele mira um padrão de uso específico: consultas analíticas que rodam milhares de vezes. Se o plano padrão é subótimo e a mesma consulta é executada repetidamente, existe economia real em descobrir, uma vez, um plano melhor.

O modelo escolhido foi um Qwen 3.8 de 4 bilhões de parâmetros, na verdade uma destilação feita por um laboratório alemão chamado Empero a partir de um Qwen 3.8 de 2,4 trilhões. Em volta dele, o autor construiu um arcabouço de agente (batizado qo-agent) com seis ferramentas: inspecionar uma tabela e suas colunas, ler estatísticas de colunas, obter o plano padrão, avaliar um candidato de verdade (medindo tempo), manter o padrão ou encerrar. O modelo emite objetos JSON descrevendo a ação que quer tomar; o arcabouço valida, transforma em hint e mede o resultado.

Primeiro, os gigantes provaram que dava

Antes de treinar nada, o autor checou se o problema era solúvel por modelos de fronteira. Em uma amostra de 10 consultas do Join Order Benchmark (113 consultas sobre a base do IMDb, criado por Leis e colegas em 2015), o GPT-6 Astra atingiu 2,54x de ganho médio quando podia propor 5 candidatos — mas apenas 0,85x quando podia propor um só. Ou seja: o ganho não vem de "saber a resposta de cara", e sim de aprender no contexto, tentando, medindo e ajustando. O Qwen 3.8 de 2,4 trilhões chegou a 2,26x.

Com isso confirmado, veio o banho de água fria. O pequeno modelo de 4 bilhões, sem treino, foi um desastre: das 113 consultas, apenas 6 terminaram com um plano válido e diferente do padrão. O modelo não conseguia nem entender o idioma do próprio arcabouço que o envolvia — errava o formato do JSON, esqueceu tabelas nas junções, chamou ferramentas inexistentes.

Aprender o idioma antes da tarefa

A solução foi destilação: usar o modelo grande como professor. Bansal gerou cerca de 500 trajetórias completas do GPT-6 Astra resolvendo consultas, e treinou o modelo pequeno para imitá-las. O ajuste foi feito com LoRA: em vez de mexer nos 4,66 bilhões de parâmetros, treinou-se um adaptador de 21,2 milhões de parâmetros — 42,5 MB, pequeno o bastante para caber numa única RTX 3090 de 24 GB.

Os resultados contam uma história interessante. Com uma época de treino, o modelo aprendeu a falar o idioma do arcabouço: os planos válidos subiram de 14 para 48 de 113 consultas — mas o desempenho caiu para 0,72x, com 16 regressões. Com duas épocas, chegou a 1,08x. Com três épocas, piorou de novo, para 0,82x — e aqui está a lição contraintuitiva: a perda medida no conjunto de validação não se moveu nada entre a segunda e a terceira época. Uma função de perda estável não significa que o modelo parou de aprender coisas úteis — pode estar aprendendo a coisa errada.

Com 300 trajetórias novas, o modelo superou o professor no que dizia respeito a montar árvores de junção válidas, chegando a 1,16x de ganho médio, com 20 consultas mais rápidas e 5 mais lentas.

O inimigo invisível: o ruído

Aqui o experimento vira uma aula de método. Para treinar por reforço, o modelo precisa de recompensa — e recompensa, nesse caso, é tempo de execução medido. O problema: medições oscilam. Bansal chegou a submeter candidatos idênticos ao plano padrão (no-op) e conferir quantas vezes o sistema de medição "se enganava", premiando um plano que era, por definição, igual ao do banco. A resposta: cerca de 5% das vezes, chegando a 13%–20% nas piores consultas.

A solução não foi estatística, foi de infraestrutura: ele aumentou o cache interno do PostgreSQL de 128 MB para 2 GB e o erro caiu quase quatro vezes, para 1,7%, praticamente desaparecendo nas consultas problemáticas. Efeito colateral bem-vindo: as próprias consultas padrão ficaram mais rápidas — o tempo somado das 113 consultas caiu de 95 para 60 segundos. Ou seja, antes de otimizar, meça direito. Metade do problema era barulho de medição, não de inteligência.

Recompensa errada ensina a resposta errada

O primeiro sistema de recompensa punia com dureza qualquer plano inválido e usava o algoritmo GRPO padrão, que compara cada tentativa com a média do grupo. O efeito foi perverso: como todas as tentativas de um grupo eram ruins, algumas delas ainda recebiam reforço positivo por serem "menos piores" — e o modelo aprendeu a devolver o próprio plano padrão do banco, que dá pouco trabalho e não gera punição. É um caso clássico de reward hacking: o modelo otimiza a métrica, não o objetivo.

A correção foi reescrever a recompensa e trocar o GRPO por uma variante "ancorada", em que cada tentativa é comparada a uma linha de base que nunca é negativa (o máximo entre zero e a média das outras tentativas do grupo). Se o grupo inteiro foi ruim, ninguém ganha crédito. Com isso, o sinal de treino passou a apontar só para planos que realmente vencem o PostgreSQL.

O resultado

Com o mecanismo consertado e uma infraestrutura assíncrona em que cada tentativa só ocupa um contêiner PostgreSQL no momento de medir (permitindo 20 tentativas simultâneas em vez de 4, já que 92% do tempo é gasto na própria inferência do modelo), o treino finalmente engrenou:

EtapaGanho médioConsultas mais rápidasRegressões
Destilação (SFT)1,16x205
Reforço, 600 atualizações1,35x340
Reforço, 1.200 atualizações1,41x382
Melhor de 15 candidatos1,81x680

Na configuração final, em que cada consulta pode gerar até 15 planos candidatos e o melhor é escolhido, o ganho médio chega a 1,81x — e o tempo total da carga de trabalho cai 44,7%, sem nenhuma regressão. Em uma das consultas, o modelo decidiu trocar uma varredura sequencial por uma varredura por bitmap depois de raciocinar sobre o número de linhas filtradas e chegou a um ganho de 90x.

Gráfico mostrando o fenômeno de plateau em otimizadores aprendidos por reforço
Figura 2(a) do paper RELOAD: o fenômeno de "plateau" — otimizadores aprendidos por reforço podem convergir para planos subótimos e ficar presos lá. É justamente o que a recompensa ancorada do experimento com o modelo de 4 bilhões tenta evitar.
Banner do projeto QORL - Query Optimization via Reinforcement Learning
O projeto foi publicado como código aberto: QORL, "Query Optimization via Reinforcement Learning". Todo o arcabouço de treino, avaliação e medição está no GitHub.

O que o modelo aprendeu de verdade

Uma das partes mais reveladoras é a análise das 1.347 ações que o modelo executou nas buscas finais. Ele pediu hints de varredura 1.141 vezes, reescreveu a ordem de junção com árvores Leading 917 vezes e ativou paralelismo 572 vezes. Correções explícitas de estimativa de linhas foram raras: apenas 146. Em 295 das 337 buscas, o modelo começou inspecionando uma tabela, estatísticas de coluna ou o plano padrão antes de propor algo — ou seja, investigou antes de chutar.

Ele desenvolveu preferências: forçar nested loops em vez de hash joins, preferir varreduras por índice e ajustar parâmetros como desligar ordenação e baixar o custo estimado de leitura aleatória. Preferências moldadas pelo reforço, consulta por consulta — não regras escritas à mão.

Quanto custou

O custo total do experimento foi de US$ 1.200: cerca de US$ 800 pelo aluguel de um nó com duas H100 por 95 horas e US$ 400 em chamadas de API para gerar as trajetórias do modelo professor. O autor observa que o projeto teria saído praticamente de graça se ele tivesse aceitado treinar nas duas RTX 3090 que já tinha em casa — apelidadas de FLOPper.

As ressalvas honestas

Nenhum experimento é definitivo, e a discussão pública apontou limites importantes. A base do IMDb usada tem cerca de 8 GB e cabe inteira na memória, com o cache do banco limitado a uma fração disso, consultas pré-aquecidas e apenas leituras — o cenário típico de um data warehouse analítico, não de um sistema transacional real. Críticos no Hacker News alertaram para o risco de excesso de ajuste ao benchmark: nada garante que os planos aprendidos sejam melhores em escala ou com cargas de escrita concorrentes.

Existe também um custo embutido: o treino exige executar a consulta dezenas ou centenas de vezes para aprender um plano melhor. Isso só compensa quando a mesma consulta roda milhares de vezes — o ganho é amortizado, não instantâneo. E há o risco de o modelo errar feio numa consulta nova, exatamente como qualquer heurística erra hoje.

O que isso significa para o Brasil

A maior parte dos sistemas brasileiros — de fintechs a secretarias de saúde, de e-commerces a hospitais — roda sobre bancos de dados relacionais como PostgreSQL e MySQL. O gargalo desses sistemas raramente é o hardware: é a consulta mal planejada que trava o relatório, atrasa o fechamento do mês e obriga a empresa a comprar mais máquina para compensar um plano ruim.

O que este experimento mostra é uma via prática e barata: não é preciso treinar um modelo gigante. Uma equipe de dados com uma carga de trabalho bem instrumentada, um ambiente de reforço honesto e um modelo aberto de 4 bilhões de parâmetros consegue melhorar o desempenho do que já está em produção — por menos de dois mil dólares. O requisito real não é orçamento de GPU, é saber medir: o experimento só avançou quando o autor tratou o ruído de medição como parte do problema.

É o tipo de aplicação de IA que quase não aparece nas manchetes, porque não conversa e não gera imagem. Só deixa o sistema mais rápido — e, no fim, é isso que paga a conta.