首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >在群里被啪啪打脸, AI 纠正了我的自负与愚蠢!

在群里被啪啪打脸, AI 纠正了我的自负与愚蠢!

作者头像
用户4035096
发布2026-07-09 20:01:34
发布2026-07-09 20:01:34
80
举报

AI 纠正了我的愚蠢: 如何让PG自定义聚合函数的finalfunc仅执行一次?

今天, IF club 群里发了一个问题: 如何让PostgreSQL自定义聚合函数的finalfunc仅执行一次?

在我的碳基神经元还停留在过去式, 记忆也出现了混乱, 也没有去看最新文档(没有使用RAG)的情况下, 非常自信的回答了:

应该是该聚合函数没有实现 parallel (PS: 其实是需要实现 COMBINEFUNC, 将不同worker的中间结果进行合并的函数), 所以会多次调用finalfunc(PS: 这是错误的). 只要在定义agg func时设置为 parallel unsafe 即可!

大错特错, 我蠢到家了. AI 狠狠的给了我一巴掌.

PS: 这些是我之前写的一些PG agg相关的文章, 仅供参考, 如果你想知道聚合的内部运算逻辑, 可以看一下:

  • 《PostgreSQL 10 自定义并行计算聚合函数的原理与实践 - (含array_agg合并多个数组为单个一元数组的例子)》
  • 《PostgreSQL 多个数组聚合为一维数组加速(array_agg)》
  • 《PostgreSQL Oracle 兼容性之 - 自定义并行聚合函数 PARALLEL_ENABLE AGGREGATE》
  • 《Greenplum 支持人为多阶段聚合的方法 - 直连segment(PGOPTIONS='-c gp_session_role=utility') Or gp_dist_random('gp_id') Or 多阶段聚合 prefunc》
  • 《Postgres-XC customized aggregate introduction》
  • 《PostgreSQL aggregate function customize》

AI 的牛逼在于它的神经元比我多多了, 同时它训练的素材也比我多多了, 并且它还有基于实时资料库的RAG, 我在AI面前就是弱鸡!

AI 纠正了我的错误

要让自定义聚合函数的finalfunc只执行一次,需要从聚合状态共享和finalfunc属性两个方面进行控制。

主要方法

1. 设置FINALFUNC_MODIFY为READ_ONLY

在创建聚合函数时指定finalfunc为只读模式:

代码语言:javascript
复制
CREATE AGGREGATE my_aggregate(input_type) (  
    SFUNC = transition_function,  
    STYPE = transition_type,  
    FINALFUNC = final_function,  
    FINALFUNC_MODIFY = READ_ONLY  
);  

FINALFUNC_MODIFY = READ_ONLY表示finalfunc不修改其参数,这是默认值(除了有序集合聚合) 。

2. 禁用聚合状态共享

通过设置shareable = false来防止多个聚合共享同一个状态值 :

代码语言:javascript
复制
// 在聚合函数的内部实现中  
peragg->shareable = false;  

3. 在finalfunc内部实现执行控制

在finalfunc中添加状态检查逻辑,确保只执行一次:

代码语言:javascript
复制
Datum  
my_finalfunc(PG_FUNCTION_ARGS)  
{  
    static bool executed = false;  
      
    if (executed)  
        PG_RETURN_NULL();  
          
    // 执行实际的final逻辑  
    executed = true;  
    // ... 你的处理逻辑  
      
    PG_RETURN_DATUM(result);  
}  

执行机制分析

PostgreSQL的聚合执行流程中,finalfunc在finalize_aggregate函数中被调用 :

  1. 每个聚合组处理完所有输入行后调用一次finalfunc
  2. 如果存在多个相同的聚合引用,它们会共享状态(当shareable=true时)
  3. finalfunc可能被重新执行,如array_agg_finalfn的注释所示

最佳实践

完整的聚合函数创建示例

代码语言:javascript
复制
-- 转换函数  
CREATEFUNCTION my_transfn(internal, integer)   
RETURNS internal AS'MODULE_PATHNAME'LANGUAGE C;  

-- 最终函数  
CREATEFUNCTION my_finalfn(internal)   
RETURNSintegerAS'MODULE_PATHNAME'LANGUAGE C IMMUTABLE;  

-- 创建聚合,确保finalfunc只执行一次  
CREATEAGGREGATE my_agg(integer) (  
    SFUNC = my_transfn,  
    STYPE = internal,  
    FINALFUNC = my_finalfunc,  
    FINALFUNC_MODIFY = READ_ONLY,  
    PARALLEL = SAFE
);  

测试验证

可以使用测试用例验证finalfunc的执行次数 :

代码语言:javascript
复制
-- 在transfn和finalfn中添加NOTICE来观察调用次数  
CREATEFUNCTION test_transfn(state int4, n int4) RETURNS int4 AS $$  
BEGIN
    RAISENOTICE'transfn called with %', n;  
    RETURN COALESCE(state, 0) + n;  
END;  
$$ LANGUAGE plpgsql;  

CREATEFUNCTION test_finalfn(state int4) RETURNS int4 AS $$  
BEGIN
    RAISENOTICE'finalfn called with %', state;  
    RETURN state;  
END;  
$$ LANGUAGE plpgsql;  

Notes

  • FINALFUNC_MODIFY有三个选项:READ_ONLY、SHAREABLE、READ_WRITE
  • 当finalfunc需要修改状态时,必须设置为READ_WRITE,这会阻止状态共享
  • 有序集合聚合的默认FINALFUNC_MODIFY是READ_WRITE
  • 聚合状态共享优化在AggInfo结构中控制

相关代码:

doc/src/sgml/ref/create_aggregate.sgml

代码语言:javascript
复制
    <term><literal>FINALFUNC_MODIFY</literal> = { <literal>READ_ONLY</literal> | <literal>SHAREABLE</literal> | <literal>READ_WRITE</literal> }</term>  
    <listitem>  
     <para>  
      This option specifies whether the final function is a pure function  
      that does not modify its arguments.  <literal>READ_ONLY</literal> indicates  
      it does not; the other two values indicate that it may change the  
      transition state value.  See <xref linkend="sql-createaggregate-notes"/>  
      below for more detail.  The  
      default is <literal>READ_ONLY</literal>, except for ordered-set aggregates,  
      for which the default is <literal>READ_WRITE</literal>.  
     </para>  

src/include/executor/nodeAgg.h

代码语言:javascript
复制
  * "shareable" is false if this agg cannot share state values with other  
  * aggregates because the final function is read-write.  
  */  
 bool  shareable;  

AI面前, 我就是小蚂蚁!

你怎么看? 欢迎留言

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-12-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 digoal德哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AI 纠正了我的愚蠢: 如何让PG自定义聚合函数的finalfunc仅执行一次?
  • AI 纠正了我的错误
  • 主要方法
    • 1. 设置FINALFUNC_MODIFY为READ_ONLY
    • 2. 禁用聚合状态共享
    • 3. 在finalfunc内部实现执行控制
  • 执行机制分析
  • 最佳实践
    • 完整的聚合函数创建示例
    • 测试验证
  • Notes
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档