Todos os produtos
Search
Central de documentação

PolarDB:pg_hint_plan

Última atualização: Jun 28, 2026

O pg_hint_plan permite incorporar dicas de plano de execução diretamente em comentários SQL, substituindo o otimizador baseado em custo do PolarDB consulta a consulta, sem afetar o restante da sessão.

/*+ SeqScan(a) HashJoin(a b) */
SELECT * FROM orders a JOIN customers b ON a.customer_id = b.id;

Como o pg_hint_plan funciona

O otimizador do PolarDB seleciona planos de execução com base em estatísticas de dados, e não em regras estáticas. Ele avalia todos os planos candidatos e escolhe aquele com o menor custo estimado. Embora essa abordagem funcione bem na maioria dos casos, o otimizador pode não identificar relações de dados menos óbvias e escolher um plano subotimizado.

Os parâmetros Grand Unified Scheme (GUC) permitem ajustar o otimizador, mas as alterações se aplicam a toda a sessão. Use o pg_hint_plan quando precisar ajustar uma única consulta sem gerar efeitos colaterais em nível de sessão.

Versões compatíveis

O pg_hint_plan está disponível nas seguintes versões:

  • PolarDB for PostgreSQL 16 (versão de revisão 2.0.16.9.6.0 ou posterior)

  • PolarDB for PostgreSQL 14 (sem exigência de versão de revisão)

  • PolarDB for PostgreSQL 11 (sem exigência de versão de revisão)

Para verificar a versão do seu cluster, execute SHOW polardb_version; no banco de dados ou visualize-a no console do PolarDB. Caso a versão de revisão não atenda ao requisito, atualize-a.

Pré-requisitos

Antes de começar, verifique se você tem:

  • Um cluster PolarDB for PostgreSQL executando uma versão compatível

  • Acesso ao banco de dados fora do Data Management (DMS) — o DMS não oferece suporte a dicas

Instalar e carregar o pg_hint_plan

Etapa 1: Criar a extensão

CREATE EXTENSION pg_hint_plan;

Etapa 2: Carregar a extensão

Escolha um dos métodos de carregamento abaixo conforme o escopo desejado:

Para um único usuário:

ALTER USER <username> SET session_preload_libraries = 'pg_hint_plan';

Para um único banco de dados:

ALTER DATABASE <database_name> SET session_preload_libraries = 'pg_hint_plan';
Se uma configuração incorreta impedir o login, conecte-se por meio de outra conta ou banco de dados e execute:
ALTER USER <username> RESET session_preload_libraries;
ALTER DATABASE <database_name> RESET session_preload_libraries;

Para um cluster de banco de dados:

Acesse o Quota Center, localize o item de cota chamado PolarDB PG pg_hint_plan use e clique em Apply na coluna Actions.

Etapa 3: Verificar se a extensão foi carregada

  1. Ative a saída de depuração:

    SET pg_hint_plan.debug_print TO on;
    SET pg_hint_plan.message_level TO notice;
  2. Execute uma consulta de teste com uma dica:

    /*+Set(enable_seqscan 1)*/SELECT 1;

    Se a extensão estiver carregada, a seguinte saída será exibida:

    NOTICE:  pg_hint_plan: used hint: Set(enable_seqscan 1)
  3. Redefina as configurações de depuração:

    RESET pg_hint_plan.debug_print;
    RESET pg_hint_plan.message_level;

Sintaxe das dicas

Um bloco de dicas começa com /*+ e termina com */. Cada dica consiste em um nome seguido de parênteses com os respectivos parâmetros, separados por espaços. Para melhorar a legibilidade, coloque múltiplas dicas em linhas separadas.

/*+
   HashJoin(a b)
   SeqScan(a)
 */
EXPLAIN SELECT *
   FROM pgbench_branches b
   JOIN pgbench_accounts a ON b.bid = a.bid
   ORDER BY a.aid;

Resultado:

QUERY PLAN
---------------------------------------------------------------------------------------
 Sort  (cost=31465.84..31715.84 rows=100000 width=197)
   Sort Key: a.aid
   ->  Hash Join  (cost=1.02..4016.02 rows=100000 width=197)
         Hash Cond: (a.bid = b.bid)
         ->  Seq Scan on pgbench_accounts a  (cost=0.00..2640.00 rows=100000 width=97)
         ->  Hash  (cost=1.01..1.01 rows=1 width=100)
               ->  Seq Scan on pgbench_branches b  (cost=0.00..1.01 rows=1 width=100)
(7 rows)

Regras de comportamento

  • O pg_hint_plan lê dicas apenas do primeiro bloco de comentários. Dicas em blocos subsequentes são ignoradas.

  • Caracteres aceitos nas dicas: letras, dígitos, espaços e _, ,, (, ). Qualquer outro caractere interrompe a análise imediatamente.

  • A correspondência de nomes de objetos diferencia maiúsculas de minúsculas (case-sensitive), diferentemente do comportamento padrão do PostgreSQL.

Exemplo — distinção entre maiúsculas e minúsculas:

Se o seu banco de dados tiver uma tabela chamada tbl, a dica a seguir não fará correspondência com ela, pois TBL e tbl são tratados como nomes diferentes:

/*+ SeqScan(TBL) */
SELECT * FROM tbl;

Use o nome exato ou o alias conforme aparece na consulta:

/*+ SeqScan(tbl) */
SELECT * FROM tbl;

Limitações em stored procedures PL/pgSQL

Ao usar o pg_hint_plan dentro de stored procedures PL/pgSQL, as dicas têm efeito apenas nos seguintes tipos de instrução:

  • SELECT, INSERT, UPDATE e DELETE

  • RETURN QUERY

  • EXECUTE QUERY

  • OPEN

  • FOR

Posicione a dica imediatamente após a primeira palavra da instrução SQL. Se colocada antes da primeira palavra, ela não será reconhecida como parte da consulta.

Tipos de dicas

O pg_hint_plan oferece suporte a seis tipos de dicas.

Dicas para métodos de varredura

Especifique o método de varredura para uma tabela. Se a tabela possuir um alias, consulte-a pelo alias.

Aplica-se a: tabelas comuns, tabelas herdadas, tabelas unlogged, tabelas temporárias, tabelas de sistema

Não se aplica a: tabelas externas, funções de tabela, expressões de valor constante, expressões universais, views, subconsultas

/*+
    SeqScan(t1)
    IndexScan(t2 t2_pkey)
 */
SELECT * FROM table1 t1 JOIN table2 t2 ON (t1.key = t2.key);

Dicas para métodos de junção

Defina o método de junção para duas ou mais tabelas.

Aplica-se a: tabelas comuns, tabelas herdadas, tabelas unlogged, tabelas temporárias, tabelas externas, tabelas de sistema, funções de tabela, expressões de valor constante, expressões universais

Não se aplica a: views e subconsultas

Dicas para ordem de junção

Determine a ordem em que as tabelas são unidas. Duas abordagens estão disponíveis:

  • Especificar a ordem de junção sem restringir a direção em cada nível.

  • Especificar a ordem e a direção da junção em cada nível.

/*+
    NestLoop(t1 t2)
    MergeJoin(t1 t2 t3)
    Leading(t1 t2 t3)
  */
SELECT * FROM table1 t1
    JOIN table2 t2 ON (t1.key = t2.key)
    JOIN table3 t3 ON (t2.key = t3.key);

Neste exemplo:

  • NestLoop(t1 t2) — une t1 e t2 usando nested loop join

  • MergeJoin(t1 t2 t3) — une t1, t2 e t3 usando merge join

  • Leading(t1 t2 t3) — define a ordem de junção como t1 → t2 → t3

Dicas para correção de número de linhas

Corrija estimativas de contagem de linhas calculadas incorretamente pelo otimizador. Quatro operadores têm suporte:

/*+ Rows(a b #10) */ SELECT ...;   -- Set join result row count to 10
/*+ Rows(a b +10) */ SELECT ...;   -- Increase row count by 10
/*+ Rows(a b -10) */ SELECT ...;   -- Decrease row count by 10
/*+ Rows(a b *10) */ SELECT ...;   -- Multiply row count by 10

Dicas para execução paralela

Especifique o plano de execução paralela para uma consulta.

Aplica-se a: tabelas comuns, tabelas herdadas, tabelas unlogged, tabelas de sistema

Não se aplica a: tabelas externas, cláusulas de valor constante, expressões universais, views, subconsultas

Use o nome real da tabela ou o alias para especificar tabelas internas dentro de uma view.

Exemplo 1: Defina o grau de paralelismo (DOP) como 3 para c1 e 5 para c2:

EXPLAIN /*+ Parallel(c1 3 hard) Parallel(c2 5 hard) */
       SELECT c2.a FROM c1 JOIN c2 ON (c1.a = c2.a);

Resultado:

QUERY PLAN
-------------------------------------------------------------------------------
 Hash Join  (cost=2.86..11406.38 rows=101 width=4)
   Hash Cond: (c1.a = c2.a)
   ->  Gather  (cost=0.00..7652.13 rows=1000101 width=4)
         Workers Planned: 3
         ->  Parallel Seq Scan on c1  (cost=0.00..7652.13 rows=322613 width=4)
   ->  Hash  (cost=1.59..1.59 rows=101 width=4)
         ->  Gather  (cost=0.00..1.59 rows=101 width=4)
               Workers Planned: 5
               ->  Parallel Seq Scan on c2  (cost=0.00..1.59 rows=59 width=4)

Exemplo 2: Defina o DOP para tl como 5:

EXPLAIN /*+ Parallel(tl 5 hard) */ SELECT sum(a) FROM tl;

Resultado:

QUERY PLAN
-----------------------------------------------------------------------------------
 Finalize Aggregate  (cost=693.02..693.03 rows=1 width=8)
   ->  Gather  (cost=693.00..693.01 rows=5 width=8)
         Workers Planned: 5
         ->  Partial Aggregate  (cost=693.00..693.01 rows=1 width=8)
               ->  Parallel Seq Scan on tl  (cost=0.00..643.00 rows=20000 width=4)

Dicas para definição de parâmetros GUC

Altere temporariamente o valor de um parâmetro GUC durante o planejamento da consulta. Ao contrário das alterações de GUC em nível de sessão, essas dicas afetam apenas a geração do plano de execução da consulta alvo. Se múltiplas dicas definirem o mesmo parâmetro GUC, a última terá efeito.

/*+ Set(random_page_cost 2.0) */
SELECT * FROM table1 t1 WHERE key = 'value';

Referência de sintaxe das dicas

Todas as dicas com suporte estão listadas abaixo. Parâmetros opcionais aparecem entre colchetes ([ ]).

Tipo Sintaxe Descrição
Métodos de varredura SeqScan(table) Força uma varredura sequencial
TidScan(table) Força uma varredura TID
IndexScan(table [index...]) Força uma varredura de índice; opcionalmente especifique um índice
IndexOnlyScan(table [index...]) Força uma varredura apenas por índice; opcionalmente especifique um índice
BitmapScan(table [index...]) Força uma varredura de bitmap; opcionalmente especifique um índice
NoSeqScan(table) Proíbe uma varredura sequencial
NoTidScan(table) Proíbe uma varredura TID
NoIndexScan(table) Proíbe uma varredura de índice
NoIndexOnlyScan(table) Proíbe uma varredura apenas por índice
NoBitmapScan(table) Proíbe uma varredura de bitmap
Métodos de junção NestLoop(table table [table...]) Força uma junção por nested loop
HashJoin(table table [table...]) Força uma junção por hash
MergeJoin(table table [table...]) Força uma junção por merge
NoNestLoop(table table [table...]) Proíbe uma junção por nested loop
NoHashJoin(table table [table...]) Proíbe uma junção por hash
NoMergeJoin(table table [table...]) Proíbe uma junção por merge
Ordem de junção Leading(table table [table...]) Especifica a ordem de junção
Leading(<join pair>) Especifica a ordem e a direção da junção em cada nível
Correção de número de linhas Rows(table table [table...] correction) Corrige a contagem estimada de linhas de um resultado de junção; operadores: #<n>, +<n>, -<n>, *<n>
Execução paralela Parallel(table <# of workers> [soft|hard]) Define ou proíbe execução paralela para a tabela especificada; 0 workers proíbe o paralelismo; soft (padrão) ajusta apenas max_parallel_workers_per_gather; hard ajusta todos os parâmetros relacionados
PX(<# of workers>) Especifica execução paralela entre nós; <# of workers> define o DOP
NoPX() Proíbe execução paralela entre nós
Definição de parâmetro GUC Set(GUC-param value) Define o valor de um parâmetro GUC durante o planejamento da consulta
Durante a execução paralela entre nós, a dica Rows(...) não tem suporte. Dicas de método de junção podem ter como alvo apenas duas tabelas por vez, e dicas de ordem de junção devem especificar todas as tabelas envolvidas.