pg_hint_plan: 简介

二月 5, 2024

摘要pg_hint_plan插件使 PostgreSQL 优化器能够针对指定查询强制执行某些决策,手动调整执行计划。

概要

pg_hint_plan可以通过在 SQL 注释中使用“提示”,比如/*+ SeqScan(a) */,来调整 PostgreSQL 执行计划。

PostgreSQL 使用的是基于成本的优化器,它会利用数据统计信息,而不是静态规则。规划器(优化器)会估算 SQL 语句的每个可能的执行计划的成本,然后执行成本最低的执行计划。规划器会尽最大努力选择最佳执行计划,但并不总是完美的,因为它没有考虑某些数据属性或列之间的相关性。

描述

基本用法

给定一条 SQL 语句,pg_hint_plan会读取其中特殊形式的注释中的提示短语。可以通过在提示前面加上序列前缀"/*+",并以"*/“结尾。提示短语由提示名称和参数组成,其中参数用括号括起来,并用空格分隔。提示短语可以使用换行符以提高可读性。

在下面的示例中,在对pgbench_accounts执行顺序扫描时,选择了哈希连接作为连接方法:

=# /*+
     HashJoin(a b)
     SeqScan(a)
    */
   EXPLAIN SELECT *
     FROM pgbench_branches b
     JOIN pgbench_accounts a ON b.bid = a.bid
     ORDER BY a.aid;
                                        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)

提示列表

下面列出了可用的提示。

分组 格式 描述
扫描方式 SeqScan(table) 强制对表进行顺序扫描。
TidScan(table) 强制对表进行 TID 扫描。
IndexScan(table[ index...]) 强制对表进行索引扫描。如果带有索引,则限制为指定的索引。
IndexOnlyScan(table[ index...]) 强制对表进行仅索引扫描。如果带有索引,则限制为指定的索引。如果仅索引扫描不可用,则可以使用索引扫描。
BitmapScan(table[ index...]) 强制对表进行位图扫描。如果带有索引,则限制为指定的索引。
IndexScanRegexp(table[ POSIX Regexp...])
IndexOnlyScanRegexp(table[ POSIX Regexp...])
BitmapScanRegexp(table[ POSIX Regexp...])
强制对表进行索引扫描、仅索引扫描(适用于 PostgreSQL 9.2 及更高版本)或位图扫描。限制为与指定的 POSIX 正则表达式模式匹配的索引。
NoSeqScan(table) 强制不要对表进行顺序扫描。
NoTidScan(table) 强制不要对表进行 TID 扫描。
NoIndexScan(table) 强制不要对表执行索引扫描和仅索引扫描。
NoIndexOnlyScan(table) 强制不要对表执行仅索引扫描。
NoBitmapScan(table) 强制不要对表执行位图扫描。
JOIN 方法 NestLoop(table table[ table...]) 强制对指定表的连接使用嵌套循环。
HashJoin(table table[ table...]) 强制对指定表的连接使用哈希连接。
MergeJoin(table table[ table...]) 强制对指定表的连接使用合并连接。
NoNestLoop(table table[ table...]) 强制不要对指定表的连接使用嵌套循环。
NoHashJoin(table table[ table...]) 强制不要对指定表的连接使用哈希连接。
NoMergeJoin(table table[ table...]) 强制不要对指定表的连接使用合并连接。
JOIN 顺序 Leading(table table[ table...]) 强制按指定的表顺序进行连接。
Leading(<join pair>) 强制按指定的表顺序和连接方向进行连接。一个连接对是用括号括起来的一对表和/或其他连接对,这样可以构成一个嵌套结构。
JOIN 时的行为控制 Memoize(table table[ table...]) 允许指定表之间连接时进行最顶层连接,以记住内部结果。不强制执行。
NoMemoize(table table[ table...]) 禁止指定表之间连接时进行最顶层连接“记忆内部结果”。
行数修正 Rows(table table[ table...] correction) 更正指定表上连接的结果的行数。可用的校正方法有绝对值(#)、加法(+)、减法(-) 和乘法(*)。它应该是 strtod() 可以理解的一个字符串。
并行查询配置 Parallel(table <# of workers> [soft|hard]) 强制或禁止对指定的表进行并行执行。<# of workers> 是所需的并行工作进程数,其中 0 表示禁止并行执行。如果第三个参数是 soft(默认值),则它只是更改max_parallel_workers_per_gather,并将其他所有内容留给规划器。设置为 hard 强制使用指定数量的并行工作进程。
GUC Set(GUC-param value) 将 GUC 参数设置为规划器运行时定义的值。