帮你快速理解、总结文档立即下载

pg_hint_plan

最近更新时间:2026-09-16 11:44:01
我的收藏
本文为您介绍 pg_hint_plan 插件的简介及使用方法。

概述

pg_hint_plan 是执行计划提示插件,通过在 SQL 语句中添加特殊注释控制优化器的执行计划,可强制指定扫描方式、连接方式、行数估计等,适用于优化器选择不当需要人工干预的场景。

支持版本

PostgreSQL 版本
内核版本
PostgreSQL 10
v10.23_r1.20及以上
PostgreSQL 11
v11.22_r1.35及以上
PostgreSQL 12
v12.22_r1.37及以上
PostgreSQL 13
v13.22_r1.32及以上
PostgreSQL 14
v14.22_r1.42及以上
PostgreSQL 15
v15.14_r1.27及以上
PostgreSQL 16
v16.10_r1.22及以上
PostgreSQL 17
v17.9_r1.16及以上
PostgreSQL 18
v18.1_r1.5及以上
说明:
您可在控制台实例详情页查看当前实例的内核版本,或执行 SHOW tencentdb_version; 查询。

插件简介

pg_hint_plan 通过 SQL 注释形式的提示(hint)干预执行计划的生成,例如 /*+ SeqScan(t) */ 强制顺序扫描、/*+ NestLoop(a b) */ 强制嵌套循环连接。提示只影响当前语句,不改变数据库对象。

环境准备

创建扩展

在目标数据库中执行以下语句创建扩展:
postgres=> CREATE EXTENSION pg_hint_plan;
CREATE EXTENSION
说明:
pg_hint_plan 的扩展安装在 hint_plan 模式下,创建时需要当前数据库的 CREATE 权限,请使用具备建库权限的账号在对应数据库执行。

扫描方式提示

以下示例创建测试表并查看默认执行计划:
postgres=> CREATE TABLE hint_test(id int PRIMARY KEY, val int);
CREATE TABLE
postgres=> INSERT INTO hint_test SELECT i, i FROM generate_series(1, 10000) AS i;
INSERT 0 10000
postgres=> ANALYZE hint_test;
ANALYZE
postgres=> EXPLAIN (COSTS OFF) SELECT * FROM hint_test WHERE id = 5000;
QUERY PLAN
------------------------------
Index Scan using hint_test_pkey on hint_test
Index Cond: (id = 5000)
(2 rows)
默认情况下,等值条件查询走主键索引扫描。

强制顺序扫描

使用 SeqScan 提示强制全表顺序扫描:
postgres=> EXPLAIN (COSTS OFF) SELECT /*+ SeqScan(hint_test) */ * FROM hint_test WHERE id = 5000;
QUERY PLAN
---------------------
Seq Scan on hint_test
Filter: (id = 5000)
(2 rows)
说明:
执行计划由默认的索引扫描变为顺序扫描,提示生效。

指定索引扫描

使用 IndexScan 提示指定扫描方式与索引:
postgres=> EXPLAIN (COSTS OFF) SELECT /*+ IndexScan(t hint_test_pkey) */ * FROM hint_test t WHERE t.id = 5000;
QUERY PLAN
------------------------------------------------
Index Scan using hint_test_pkey on hint_test t
Index Cond: (id = 5000)
(2 rows)

连接方式提示

以下示例创建第二张表并查看默认连接计划:
postgres=> CREATE TABLE hint_dept(id int PRIMARY KEY, dname text);
CREATE TABLE
postgres=> INSERT INTO hint_dept VALUES (1,'dev'), (2,'ops'), (3,'qa');
INSERT 0 3
postgres=> ANALYZE hint_dept;
ANALYZE
postgres=> EXPLAIN (COSTS OFF) SELECT * FROM hint_test t JOIN hint_dept d ON t.val = d.id;
QUERY PLAN
-------------------------------
Hash Join
Hash Cond: (t.val = d.id)
-> Seq Scan on hint_test t
-> Hash
-> Seq Scan on hint_dept d
(5 rows)
默认连接方式为 Hash Join。使用 NestLoop 提示强制嵌套循环连接:
postgres=> EXPLAIN (COSTS OFF) SELECT /*+ NestLoop(t d) */ * FROM hint_test t JOIN hint_dept d ON t.val = d.id;
QUERY PLAN
-------------------------------
Nested Loop
Join Filter: (d.id = t.val)
-> Seq Scan on hint_test t
-> Materialize
-> Seq Scan on hint_dept d
(5 rows)
说明:
连接方式由 Hash Join 变为 Nested Loop,提示生效。

行数估计提示

使用 Rows 提示调整连接结果的行数估计,影响优化器的代价计算:
postgres=> EXPLAIN SELECT /*+ Rows(t d #10) */ * FROM hint_test t JOIN hint_dept d ON t.val = d.id;
QUERY PLAN
-----------------------------------------------------------------------
Hash Join (cost=1.07..172.33 rows=10 width=15)
Hash Cond: (t.val = d.id)
-> Seq Scan on hint_test t (cost=0.00..145.00 rows=10000 width=8)
-> Hash (cost=1.03..1.03 rows=3 width=7)
-> Seq Scan on hint_dept d (cost=0.00..1.03 rows=3 width=7)
(5 rows)
说明:
Rows(t d #10) 将连接结果行数估计指定为10(# 表示绝对值),实际估计值由默认的3行调整为10行。也可用 +n(加值)、-n(减值)、*n(倍数)方式调整。

常用提示速查

提示
说明
SeqScan(表)
强制顺序扫描
IndexScan(表 [索引])
强制索引扫描,可指定索引名
BitmapScan(表 [索引])
强制位图扫描
NestLoop(表1 表2)
强制嵌套循环连接
HashJoin(表1 表2)
强制哈希连接
MergeJoin(表1 表2)
强制合并连接
Rows(表1 表2 #n)
调整连接行数估计
Leading(表1 表2)
指定连接顺序

常见问题

Q:使用 Rows 提示时报 Rows hint requires at least two relations?

A:Rows 提示用于调整连接结果的行数估计,需要至少指定两个关系。单表的行数估计暂不支持通过该提示调整。

Q:提示写在什么位置?

A:提示写在 SQL 语句的注释中,格式为 /*+ 提示内容 */,紧跟在 SELECTUPDATEDELETE 等关键字之后。提示语法错误时会输出 INFO 级别日志但不影响语句执行。

相关参考