FlinkSQL-自定义聚合函数AggregateFunction

本文深入探讨了Apache Flink中的用户自定义聚合函数(UDAF),如何通过继承AggregateFunction实现自己的聚合操作。内容包括聚合函数的概念、实现方法、工作原理以及代码示例,展示了如何计算平均温度的自定义聚合函数,并提供了测试用例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是聚合函数

聚合,多对一,类似窗口聚合

  • 用户自定义聚合函数(User-Defined Aggregate Functions,UDAF)可以把一个表中的数据,聚合成一个标量值
  • 用户定义的聚合函数,是通过继承 AggregateFunction 抽象类实现的

聚合函数的实现

AggregationFunction要求必须实现的方法

  • createAccumulator()
  • accumulate()
  • getValue()

聚合函数的工作原理

  • 首先,它需要一个累加器(Accumulator),用来保存聚合中间结果的数据结构;可以通过调用 createAccumulator()方法创建空累加器
  • 随后,对每个输入行调用函数的 accumulate() 方法来更新累加器
  • 处理完所有行后,将调用函数的 getValue() 方法来计算并返回最终结果

代码实现

    //实现自定义的AggregateFunction<结果值,中间状态>
    public static class AvgTemp extends AggregateFunction<Double, Tuple2<Double,Integer>> {
        //输出结果
        @Override
        public Double getValue(Tuple2<Double, Integer> acc) {
            return acc.f0/acc.f1;
        }
        //初始化累加器
        @Override
        public Tuple2<Double, Integer> createAccumulator() {
            return new Tuple2<Double,Integer>(0.0,0);
        }
        //必须实现一个accumulate(中间状态,传入的一条数据)方法,来数据之后更新状态
        public void accumulate(Tuple2<Double,Integer> acc, Double temp){
            acc.f0 += temp;
            acc.f1 += 1;
        }
    }

测试用例

		//流转换成表 Tuple3<String,Long,Double>
        Table sourceTable = tableEnv.fromDataStream(dataStream, "f0 as id, f1 as ts, f2 as temp,pt.proctime");
        //在环境中注册UDAF
        AvgTemp avgTemp = new AvgTemp();
        tableEnv.registerFunction("avgTemp",avgTemp);
        //tableAPI
        Table resultTable = sourceTable.groupBy("id")
                .aggregate("avgTemp(temp) as avgtemp")
                .select("id,avgtemp");
        tableEnv.toRetractStream(resultTable, Row.class).print();
        //SQL
        tableEnv.createTemporaryView("sensor",sourceTable);
        Table resultSqlTbale = tableEnv.sqlQuery("select id,avgTemp(temp) as avgtemp from sensor group by id");
        tableEnv.toRetractStream(resultSqlTbale,Row.class).print();
### 集成并使用自定义 HyperLogLog 实现数据去重 为了在 Flink SQL 中集成并使用自定义的 HyperLogLog 算法进行数据去重,主要涉及几个方面的工作:创建用户自定义聚合函数(UDAGG),注册该函数Flink 表环境中,并编写相应的 SQL 查询语句。 #### 创建用户自定义聚合函数 首先,在 Java 或 Scala 编程环境下构建一个实现了 `AggregateFunction` 接口的新类。这个类负责处理输入记录流并将结果汇总为单一输出值——即 HyperLogLog 结构表示的独特元素集合估计数。下面是一个简单的例子: ```java import org.apache.flink.table.annotation.DataTypeHint; import org.apache.flink.table.functions.AggregateFunction; public class CustomHLLAgg extends AggregateFunction<Long, HLLState> { @Override public Long getValue(HLLState acc) { return acc == null ? 0L : acc.getEstimate(); } @Override public HLLState createAccumulator() { return new HLLState(); // 初始化状态对象 } public void accumulate(HLLState acc, String value) { if (value != null && !value.isEmpty()) { acc.add(value.hashCode()); } } private static final long serialVersionUID = 1L; } ``` 此代码片段展示了如何定义一个新的 UDAGG 函数 `CustomHLLAgg` 来累积字符串类型的唯一键值[^1]。 #### 注册 UDF 至 Flink Table Environment 接着,需要将上述编写的 UDAGG 添加至正在运行的应用程序上下文中以便后续调用。这一步骤通常是在应用程序启动初期完成的一次性设置工作。 ```scala val env = StreamExecutionEnvironment.getExecutionEnvironment val tEnv = StreamTableEnvironment.create(env) // 假设已经打包好了 jar 文件路径如下所示 tEnv.registerJavaFunction("custom_hll", "com.example.CustomHLLAgg") // 如果是 scala 版本,则可能是这样的形式 // import org.apache.flink.api.scala._ // val customHLLFunc = new CustomHLLAgg() // tEnv.registerFunction("custom_hll", customHLLFunc) ``` 这段脚本说明了怎样加载外部 JAR 并向当前会话环境暴露新的命名空间下的方法名 `custom_hll`[^2]。 #### 执行带有自定义 HLL 的 SQL 查询 最后,利用之前准备好的一切资源执行一条标准的 SQL SELECT 语句即可达到目的。这里给出了一条示范性的命令行指令作为参考: ```sql INSERT OVERWRITE dws_goods_uv PARTITION(dt='${dt}', hm='${hm}') SELECT goods_id, custom_hll(mid) AS unique_mid_count -- 使用自定义 hll 函数统计 distinct mid 数量 FROM dwd_table_goods WHERE dt = '${dt}' AND hm = '${hm}' GROUP BY goods_id; ``` 这条 SQL 语句模仿了提供的示例[^4],但是替换了原有的 `estimate_prepare()` 方法为新引入的 `custom_hll()` 用户定义聚集函数来进行更精确高效的近似计数运算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值