默认情况下,函数只是一个数据库系统对其行为知之甚少的“黑盒”。但是,这意味着使用该函数的查询执行效率可能远低于预期。可以提供额外的信息来帮助规划器优化函数调用。
一些基本事实可以通过在CREATE FUNCTION
命令中提供的声明性注释来提供。其中最重要的是函数的易变性类别(IMMUTABLE
、STABLE
或VOLATILE
);在定义函数时,应始终小心正确地指定此类别。如果希望在并行查询中使用函数,则还必须指定并行安全属性(PARALLEL UNSAFE
、PARALLEL RESTRICTED
或PARALLEL SAFE
)。指定函数的估计执行成本和/或返回集合的函数估计返回的行数也很有用。但是,以声明方式指定这两个事实的方式仅允许指定常量值,这通常是不够的。
还可以将规划器支持函数附加到 SQL 可调用的函数(称为其目标函数),从而提供有关目标函数的知识,这些知识过于复杂而无法以声明方式表示。规划器支持函数必须用 C 编写(尽管其目标函数可能不是),因此这是一个高级功能,相对较少的人会使用。
规划器支持函数必须具有以下 SQL 签名
supportfn(internal) returns internal
通过在创建目标函数时指定SUPPORT
子句将其附加到目标函数。
规划器支持函数的 API 详细信息可以在PostgreSQL源代码中的src/include/nodes/supportnodes.h
文件中找到。这里我们仅提供规划器支持函数可以做什么的概述。对支持函数的可能请求集是可扩展的,因此在将来的版本中可能会有更多功能。
某些函数调用可以在计划期间根据特定于函数的属性进行简化。例如,int4mul(n, 1)
可以简化为n
。这种类型的转换可以通过规划器支持函数来执行,方法是让它实现SupportRequestSimplify
请求类型。对于在查询解析树中找到的目标函数的每个实例,都会调用支持函数。如果它发现特定调用可以简化为其他形式,它可以构建并返回表示该表达式的解析树。这也会自动适用于基于该函数的操作符——在上面给出的示例中,n * 1
也会简化为n
。(但请注意,这只是一个示例;此特定优化实际上并非由标准PostgreSQL执行。)我们不保证PostgreSQL永远不会在支持函数可以简化的案例中调用目标函数。确保简化表达式与目标函数的实际执行之间存在严格的等价关系。
对于返回boolean
的目标函数,通常很有用的是估计使用该函数的WHERE
子句将选择的行的比例。这可以通过实现SupportRequestSelectivity
请求类型的支持函数来完成。
如果目标函数的运行时间高度依赖于其输入,则为其提供非恒定成本估算可能很有用。这可以通过实现SupportRequestCost
请求类型的支持函数来完成。
对于返回集合的目标函数,通常很有用的是为将返回的行数提供非恒定估算。这可以通过实现SupportRequestRows
请求类型的支持函数来完成。
对于返回boolean
的目标函数,可以将出现在WHERE
中的函数调用转换为可索引的操作符子句或子句。转换后的子句可能与函数的条件完全等效,或者它们可能稍微弱一些(即,它们可能接受函数条件不接受的一些值)。在后一种情况下,索引条件被称为有损;它仍然可以用于扫描索引,但必须对索引返回的每一行执行函数调用,以查看它是否确实通过了WHERE
条件。要创建此类条件,支持函数必须实现SupportRequestIndexCondition
请求类型。
如果您在文档中看到任何不正确的内容、与您对特定功能的体验不符的内容或需要进一步说明的内容,请使用此表单报告文档问题。