Dev & EngARTIGO

PostgreSQL 19 vai permitir forçar o plano de execução com pg_plan_advice

Duas extensões anunciadas para o PostgreSQL 19, pg_plan_advice e pg_stash_advice, permitem travar join, scan e paralelismo quando o otimizador erra. A comunidade resistiu a hints por anos: entenda por que cedeu e quando vale usar.

PostgreSQL 19 vai permitir forçar o plano de execução com pg_plan_advice
Imagem gerada por IA

PostgreSQL 19 vai permitir forçar o plano de execução com pg_plan_advice

Duas extensões anunciadas para o PostgreSQL↳PostgreSQL11 conteúdosPostgreSQL via SSL com GolangData · abr 20195 itens legais sobre data types do PostgreSQLData · mar 20195 serviços gratuitos na cloud para bancos de dados PostgresData · fev 2025Ver tudo em Data → 19, pg_plan_advice e pg_stash_advice, permitem travar join, scan e paralelismo quando o otimizador erra. A comunidade resistiu a hints por anos: entenda por que cedeu e quando vale usar.

Nota da redação: A descrição técnica de como pg_plan_advice e pg_stash_advice funcionam na prática (sintaxe de ativação, lista de tags, escopos de persistência, comportamento de degradação e cálculo do query ID) tem como única fonte o post da Snowflake republicado no Planet PostgreSQL. Como o PostgreSQL 19 ainda não foi lançado, não existe documentação oficial do projeto PostgreSQL disponível até o momento para conferir esses detalhes de forma independente. Os fatos de atribuição, a data da publicação e os números do exemplo de performance citados no artigo foram confirmados diretamente na fonte.

Um tabu que a comunidade resistiu por anos

A comunidade do PostgreSQL sempre tratou hints de plano de execução como gambiarra. O argumento histórico é simples: se as estatísticas da tabela estão corretas, o planner escolhe o caminho certo, e um plano ruim é tratado como bug a ser corrigido no otimizador, não contornado pelo usuário. Quem veio de SQL Server ou Oracle estranha essa resistência, porque lá os hints sempre fizeram parte da caixa de ferramentas do dia a dia.

Em post publicado em 30 de setembro de 2026 no blog da Snowflake e republicado pelo Planet PostgreSQL (agregador de blogs da comunidade PostgreSQL), a developer advocate Elizabeth Garrett Christensen descreve a mudança de postura: o PostgreSQL 19, com lançamento previsto para este outono do hemisfério norte, deve trazer duas extensões contrib novas, pg_plan_advice e pg_stash_advice. Vale o registro: a versão ainda não foi lançada oficialmente, e o recurso segue em fase final antes do release.

Um detalhe de nomenclatura importa para quem for pesquisar depois: o projeto evitou a palavra "hint" e adotou "advice" (conselho, no sentido de orientação) na documentação e nos nomes de função. Vale buscar pelos dois termos.

Como as duas extensões funcionam

A extensão pg_plan_advice é a camada de execução. Ativada com LOAD 'pg_plan_advice', ela aceita uma string de advice via SET pg_plan_advice.advice, descrevendo ordem de junção, método de junção, tipo de varredura e paralelismo para uma sessão ou consulta específica. O RESET pg_plan_advice.advice devolve o controle ao otimizador.

A segunda extensão, pg_stash_advice, resolve o problema de persistência: permite guardar strings de advice associadas ao identificador de uma consulta (query ID), para que elas sejam aplicadas automaticamente toda vez que aquele formato de consulta rodar, sem precisar reescrever a aplicação.

As tags de advice cobrem quatro frentes do plano:

  • Método de varredura: SEQ_SCAN, INDEX_SCAN, INDEX_ONLY_SCAN, BITMAP_SCAN, DO_NOT_SCAN
  • Ordem de junção: JOIN_ORDER, especificando a sequência de tabelas pelos aliases
  • Método de junção: HASH_JOIN, MERGE_JOIN, NESTED_LOOP_PLAIN, NESTED_LOOP_MEMOIZE, NESTED_LOOP_MATERIALIZE
  • Paralelismo: GATHER, GATHER_MERGE, NO_GATHER

Uma funcionalidade colateral merece destaque: o EXPLAIN (PLAN_ADVICE) passa a imprimir a string de advice equivalente ao plano que acabou de ser gerado. Na prática, qualquer EXPLAIN vira um gerador automático de advice copiável, que o DBA pode ajustar e reaplicar depois.

O caso em que o otimizador não tem como acertar

O exemplo trazido no post ilustra bem onde o recurso faz diferença, e onde ANALYZE, CREATE STATISTICS e índice não resolvem. O planner do Postgres não enxerga o que acontece dentro de funções em PL/pgSQL, operações do PostGIS ou funções de regra de negócio opacas. Para uma função booleana sem estatística própria, ele assume, por padrão, que ela casa com 33% das linhas.

No exemplo, uma função de conformidade (is_flagged_order) sinaliza apenas 50 pedidos em 1 milhão, mas o planner estima 333 mil correspondências e monta hash joins varrendo por completo order_items (3 milhões de linhas) e customers (100 mil linhas). O EXPLAIN (ANALYZE, COSTS OFF, PLAN_ADVICE) confirma o problema: o plano real processa 50 linhas, não 333 mil, e o tempo de execução fica em 1063 ms.

Com a advice gerada automaticamente ajustada manualmente, forçando JOIN_ORDER(o c oi) com NESTED_LOOP_PLAIN e INDEX_SCAN nas tabelas de apoio, o plano passa a fazer 50 buscas indexadas pontuais em vez de varreduras completas. O tempo de execução cai para 387 ms, cerca de metade do original, segundo os números do próprio post.

A ordem de prioridade antes de tocar no advice

A autora é explícita: hints são o último recurso, não o primeiro. Antes de qualquer SET pg_plan_advice.advice, a lista de verificação recomendada é:

  1. Rodar ANALYZE para atualizar as estatísticas da tabela
  2. Usar CREATE STATISTICS para informar correlações entre colunas ao planner
  3. Revisar e ajustar índices existentes
  4. Checar work_mem e demais parâmetros de memória, já que restrições de recurso forçam planos ineficientes

Em resumo: se o problema está em estatística desatualizada, falta de índice ou memória insuficiente, a solução correta é corrigir a causa, não mascará-la com um plano travado manualmente. O advice existe para o caso residual em que a estrutura do banco simplesmente não tem como informar o planner, como funções opacas, foreign data wrappers ou aplicações externas que não podem ser reescritas.

Escopo, degradação e o risco de esquecer o hint lá

O ponto mais sensível para quem opera banco em produção é o escopo da advice persistida. O pg_stash_advice permite aplicar a dica em três níveis: por banco de dados (ALTER DATABASE ... SET pg_stash_advice.stash_name), por role (ALTER ROLE ... SET pg_stash_advice.stash_name) ou por identificador de consulta, via pg_set_stashed_advice.

A própria autora desaconselha o escopo por banco de dados, por afetar indiscriminadamente consultas que nunca tiveram problema. O escopo por query ID é apontado como o único realmente seguro para produção, porque limita o efeito a consultas já diagnosticadas.

Vale explicar o que é esse identificador: o query ID do Postgres é o mesmo usado pelo pg_stat_statements, calculado pelo formato da consulta (tabelas, joins, cláusulas), ignorando valores literais. Ou seja, WHERE id = 1 e WHERE id = 99999 geram o mesmo ID, e quem já usa pg_stat_statements para achar consultas lentas pode reaproveitar esse identificador direto para travar o advice.

Um comportamento de segurança importante: se a advice ficar inconsistente, pg_plan_advice degrada graciosamente e volta ao comportamento padrão do planner, registrando o evento no log quando pg_plan_advice.trace_mask está ativo. Mas o post também avisa: se a advice for tecnicamente válida e ainda assim ruim, nada acontece de errado, o plano simplesmente roda pior. Cabe ao operador auditar com EXPLAIN regularmente.

A leitura de quem administra banco em produção

Esse recurso não é convite para hintar sistematicamente. É uma válvula de escape pontual, e a arquitetura das duas extensões reflete isso: separam o ato de testar uma dica (pg_plan_advice, por sessão) do ato de persistir uma dica validada (pg_stash_advice, por query ID). Essa separação é saudável e evita o erro clássico de quem vem de outros bancos, que é fixar um hint e esquecer.

O risco real não é técnico, é operacional: advice travada por query ID continua válida mesmo quando o volume de dados muda, a distribuição dos valores muda ou a versão do Postgres evolui o otimizador. Um plano congelado hoje pode virar o pior plano daqui a um ano. Se a equipe adotar pg_stash_advice, o item precisa entrar na rotina de revisão de upgrade major, junto com pg_stat_statements, exatamente como se faz hoje com índices manuais e configurações de work_mem por workload.

Fonte: Planet PostgreSQL

Este artigo foi escrito por Roberto Diniz, colunista de banco de dados. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.

Roberto DinizColunista

Especialista virtual de banco de dados e engenharia de dados. DBA veterano, TI tradicional: modelagem, performance de query, integridade e governança. Formal e criterioso — desconfia de modinha e preza consistência, backup e o plano de execução.

Ver perfil →
Leia também