00:00
关于用户自定义函数udf这一部分呢?最后我们再来讲解一个比较复杂的类型,那就是表聚合函数table aggregate方式。那这样一个表聚合函数呢,可以认为是之前我们讲到的表函数和聚合函数的一个结合体啊,之前我们说表函数可以认为是一对多的转换,一条数据输入,诶直接转换之后呢,就可以把它扩展成一张表,多行的输出,然后再进行一个连接啊,跟之前的表进行一个扩充,而对于聚合函数而言呢,它相当于是把收集到的多条数据,可能是分组之后的数据,然后经过聚合计算之后得到唯一的一个聚合结果,那现在的表聚合函数呢,那就是同样还是收集多条数据,然后进行聚合统计之后呢?诶,同样可以扩展出多条输出结果,那就相当于得到的聚合结果又是一张表了,这是一个多对多的转换。
01:00
啊,所以它就会更加复杂一点,那在具体代码实现过程当中呢,其实这个表聚合函数跟聚合函数是非常像的啊,因为它本质上都是要做一个聚合嘛,那之前我们定义聚合函数的时候,是要继承抽象类aggregate function,那现在呢,表聚合函数继承的就是table aggregate function。那它里边的内部结构跟every的方式非常的相似,它也是两个外形参数,一个T表示的是输出的结果数据类型,那ACC表示的就是中间累积状态啊,这个累加器的数据类型,那聚合函数当中呢,必须实现三个方法,那现在在表聚合函数当中也是有对应的三个方法,一个叫做create accumul,创建一个累加器啊,那这就是我们中间聚合状态的数据类型啊,然后呢,还有一个核心的计算方法叫做accumulate啊,这个也是本身当前的抽象类,并没有给我们提供对应的抽象方法,但是呢,底层要求我们就叫这个名字啊,而且必须得实现,这是每来一条数据之后都要调用的核心的聚合计算方法。
02:05
最后呢,还有一个发出数据的方法,哎,之前我们说在聚合函数里边,它就是直接get value,获取最终的这个返回值就可以了,而且我们也看到了啊,在这个that value里边,它是有一个返回值的类型的,我们想要得到什么样的数据类型直接返回,所以我们就想到了,那对于之前的巨头函数,它是只有一个返回结果啊,多对一嘛,那当然就是直接返回值就行了,那现在我们这个表聚函数呢,它多对多有可能有多条返回数据,那这个时候显然就不应该让他直接有一个返回值了。所以现在我们最后得到返回结果的这个方法呀,就不叫做get value,而是叫做it value,它不是直接获取,而是主动去做发射,发送出一个我们想要的结果值,那所以这个it value里边呢,它本身就没有返回值,而是要使用收集器,我们之前非常熟悉的collect啊,那这个类型,那就是我们调用一次collect的方法,这样就可以输出一行数据,这样的话就可以实现一个多对多的转换,输出一张结果表。
03:13
哎,那我们可能会想到就是对于这个表聚合函数啊,它整的这么复杂,用在什么场合里呢?一般意义上的这种聚合,我们前面用安的方式自定义一下啊,只要把中间类型整的复杂一点,计算逻辑复杂一点,那就可以实现绝大多数的聚合场景需求了。那对于有一些特定的场合,只输出一个聚合结果的aggregate function就搞不定,比如前面我们提到过的top n。啊,他文我们讲到啊,本质上来讲,你做这个top的判断肯定是要统计一个值嘛,所以这个值的统计过程就是一个聚合的过程,聚合起来之后呢,还要做排序,还要输出多条信息,比方说最简单的套泡查询,我们就相当于输出的是两行数据的一张表,然后呢,每来一个数据之后,这张表可能还要做更新,我们现在没有现成的这个系统函数,直接可以调这个TOP2啊,直接获取到它的这个前两名的数据,诶那怎么办呢?之前我们讲的CQ里边的通用方法,那是啊,相当于内置的做了一个优化啊,直接使用一个分组聚合,或者是一个窗口聚合,结合一个开窗函数,结合over的一个排序,然后最终使用一个number这样的聚合函数啊,把它的排序之后的行号提取出来,最终筛选出套盆。
04:32
那我们自然想到了,那如果说啊,想要去自定义实现一个这样的套喷该怎么写呢?啊,那就只有用表聚合函数去实现了,整体的思路其实也比较简单啊,就是在这个累加器里边。我们中间聚合状态保存什么呢?就保存当前的最大的两个值嘛,比方说是TOP2的话,我就保存当前最大的一个值和第二大的一个值,然后每来一条新的数据之后呢,就跟这个累加器当中的两个值进行比较啊,先判断是否比最大的大,如果比最大的大的话,那就后边都往后瞬移,最后一个就啊,相当于就退出我们当前保存的状态了,那如果要是比最大的小的话,再依次朝下比,再比第二大啊,如果大的话就替换它,那其实我们知道TOP2比较简单,只要比较两次,如果是top top10的话,那可能就有可能要一次一个一个比下去,所以这个实现的过程还是比较麻烦。
05:27
所以接下来我们就在代码当中来尝试一下,看看怎么样实现这个top需求吧。
我来说两句