当您调用 DELETE、INSERT、SELECT 或 UPDATE 命令时,服务器会生成一组执行计划;在分析这些执行计划之后,服务器会选择一个计划,该计划将(通常)在最短的时间内返回结果集。

服务器的计划选择取决于几个因素:

  • 数据处理操作的估计执行成本。
  • 分配给 postgresql.conf 文件 Query Tuning 部分中参数的参数值。
  • ANALYZE命令收集的列统计信息。

通常,查询计划程序将选择最便宜的计划。您可以在选择查询计划时使用optimizer hint来影响服务器。optimizer hint是嵌入在紧跟 DELETE、INSERT、SELECT 或 UPDATE 命令后、类似注释的语法中的一条指令(或多条指令)。注释中的关键字指示服务器在生成结果集时使用或避免特定计划。

{ DELETE | INSERT | SELECT | UPDATE } /*+ { hint [ comment ] } [...] */
 statement_body

{ DELETE | INSERT | SELECT | UPDATE } --+ { hint [ comment ] } [...]
 statement_body

optimizer hint可包含在上面显示的任一形式中。请注意,在两种形式中,加号 (+) 必须紧跟 /* 或 -- 开始注释符号,没有任何中间空格,否则服务器不会将以下标记解读为hints。

如果您使用的是第一种形式,则hint和可选注释可能跨越多行。第二种形式要求所有hint和注释占据一行;语句的其余部分必须在新的一行开始。

说明
  • 如果可能,数据库服务器将始终尝试使用指定的hint。
  • 如果设置计划程序方法参数以禁用某种计划类型,则即使在hint中指定了该计划,也不会使用此计划,除非计划程序没有其他可行的选项。计划程序方法参数的示例为 enable_indexscan、enable_seqscan、enable_hashjoin、enable_mergejoin和 enable_nestloop。这些均为布尔参数。
  • 请记住,hint嵌入在注释中。因此,如果hint拼写错误或者视图、表或列名称等hint的任何参数拼写错误,或者 SQL 命令中不存在该参数,则不会显示发生了任何类型的错误。不会给出任何语法错误,只会忽略整个hint。
  • 如果在 SQL 命令中将别名用于表或视图名称,则必须在hint中使用别名而不是原始对象名。例如,在命令 SELECT /*+ FULL(acct) */ * FROM accounts acct ..., acct 中,必须在 FULL hint中指定 accounts 的别名,而不是表名 accounts。

使用 EXPLAIN 命令可确保hint采用正确的形式并且计划程序使用hint。

一般来说,不应在生产应用程序(其中表数据在应用程序的整个生命周期中都会发生变化)中使用optimizer hint。通过确保经常对动态列使用 ANALYZE 命令,列统计信息将更新以体现值更改,并且计划程序将使用此类信息为任何给定的命令执行生成最低成本计划。使用optimizer hint会破坏此过程的目的,并且无论表数据如何变化,都将产生相同的计划。

参数

参数 说明
hint 优化器提示指令。
comment 带有附加信息的字符串。请注意,注释中可以包含哪些字符存在限制。通常,comment 只能包含字母、数字、下划线、美元符号、数字符号和空格字符。这些字符还必须符合标识符的语法。如果注释并非这种形式,将忽略任何后续hint。
statement_body DELETE、INSERT、SELECT 或 UPDATE 命令的其余部分。

以下各节更详细地介绍optimizer hint指令。