PostgreSQL如何根据函数参数动态设置返回行估计值
PostgreSQL plpgsql集合返回函数动态行数估计说明
你尝试的如下写法无法生效:
CREATE OR REPLACE FUNCTION some_func (x int[], OUT xxx int, OUT yyy int) RETURNS SETOF record LANGUAGE plpgsql AS $$ DECLARE foo int; BEGIN RETURN query SELECT 5, 3; END; $$ ROWS array_length(x, 1) * 2; -- 此处写法不生效
这是PostgreSQL的固有语法限制:CREATE FUNCTION定义中跟在函数体后的ROWS子句仅支持传入常量整数值,不允许引用函数入参,也不支持运行时动态计算的表达式。这个值是在函数创建的解析阶段就被确定存入系统目录的,此时入参x还没有实际赋值,自然无法通过array_length(x,1)*2这类引用参数的表达式动态生成估计值。
可落地的替代处理方式
- 直接设置量级匹配的固定ROWS值
ROWS参数的作用仅仅是给查询规划器提供成本估算的参考,不会限制函数实际返回的行数。只要你设置的常量和实际返回行数量级没有跨数量级的偏差(比如实际返回上万行你写ROWS 10,或者实际返回个位数你写ROWS 10000),对执行计划的负面影响很小,普通业务场景下完全够用。 - 依赖版本自带的统计缓存
PostgreSQL 12及之后的版本,会自动缓存plpgsql函数历史执行时的实际返回行数统计,后续执行相同参数的函数时,规划器会优先使用缓存的真实统计值做估算,准确度远高于手动设置的固定ROWS值,不需要额外配置。 - 高精度估算场景的实现
如果对行数估算精度有极高要求,可以通过C语言编写自定义函数,注册专属的行数估计回调,在查询规划阶段读取传入参数的值计算估计行数;也可以借助对应功能的第三方扩展实现,不过这类方案实现成本高,非特殊场景不推荐使用。
额外提示:你给出的示例函数定义存在冗余:已经声明了
OUT xxx int, OUT yyy int两个输出参数时,不需要额外写RETURNS SETOF record,直接返回SETOF对应的隐式组合类型即可。
内容的提问来源于stack exchange,提问作者Alexandr X.
相关产品推荐
相关产品推荐

