00:00
另外一种套喷的需求,那就是所谓的窗口套,因为之前我们做这个套喷N统计的时候呢,是针对当前的所有数据,因为我们知道就相当于是在当前得到的这张表里边做了一个统计,出来一个单独的字段,然后进行排序,取前前几名啊,那这个就相当于是针对所有数据有效的。那在实际的应用场景当中呢,我们往往不会对全量的数据去做统计,而是针对某段时间内,某段范围内的数据进行统计,所以那当然就是需要先开窗口,然后基于窗口去统计对应的top n了。那在电商行业里边有一个非常常见的需求,就是统计一段时间内的热门商品。那这个之前我们都已经实现过,非常简单,那就是先开窗口,比方说我们统计一天之内的热门商品,那我们就先开一个一天的长度为一天的滚动时间窗口,然后在窗口当中我们统计每一个商品的热门度,那一般这个热门度可以用它的访问量啊,点击的次数来进行表示,所以我们可以统计每个商品被点击的次数,然后按照窗口进行分组,按照点击量的大小做一个降序,排序取前N个就是我们当前的top n热门商品。
01:25
那这种实现的方式呢?前在介绍处理函数process的时候,曾经利用定义的列表状态。对之前所有收集到的数据做了一个。值的缓存,然后接下来我们可以自己去把它放在一个列表里边进行排序,Salt之后提取前N降啊,这样的话就实现了对应的炮,但是我们知道process啊,处理函数是非常底层的API啊,在那个过程当中,我们不光用到了状态,还用到了定时器,那这种实现当然是非常复杂非常麻烦的。
02:05
能不能直接在flink CQ,我们直接写一条CQ就能把对应的窗口这个需求实现呢?当然也是可以的,本质上来说,当前的top n的实现在CQ里边,跟前面我们介绍的普通的top n是类似的。简单来讲就是先做一个窗口聚合,然后聚合之后得到的信息就包含了窗口的Windows start window and啊,那我们就连同每个商品的点击量啊,统计出来的那个count值一并返回,然后得到的这张表呢,接下来就像普通的top那样去定义一个over窗口,按照窗口进行分组,诶,之前我们统直接做这个统计的时候没有定义petition by,那现在呢,就要进行分组了,分组的字段是基于窗口来做的这样的操作,哎,所以我们在这里。
03:04
直接利用这个窗口的PTF进行统计之后,聚合之后得到的Windows start window and就有用了,它可以用来做我们当前over窗口里边分组的那个K分组的字段,分区的字段。同样后边做排序的话,还是按照当前的统计出来的数量进行一个降序排列,那当然了,呃,我们最终聚合出来的应该还是一个row number,统计一下当前的行号,然后再加一个where筛选条件,选取前N行就可以得到对应的结果。好,那接下来我们还是在代码里边做一个具体的实现啊,当然了,我们在具体实现的过程当中会发现当前的这个event里边并没有商品。具体的一些信息,那所以如果说我们当前这个URL。这里边啊,如果全是跟商品有关的话,或许我们可以提取这个某一个商品的这个ID,按ID去做一个分组啊,但是我们现在的话,好像没有更多的商品信息。
04:09
URL不能代表具体的商品,所以我们就不要实现具体的这个热门商品的需求了,我们来实现另外一个需求,那就是跟之前一样,也是按照用户去做一个分组的统计,我们统计每一个小时里边,比方说或者说呃,我们当前数据这个比较少的话,统计每十秒钟。当中。有最多访问行为的用户,也就是说看哪个用户点击访问所有的页面啊,它的点击行为最多啊。这就类似于之前我们做的这个普通的top n的这个实现了啊,那相当于也是把当前用户他的统计行为在窗口内做一个统计,统计出来之后按照C的大小从大到小降序排列统计出行号来,然后number小于等于二,这样的话就可以,所以相当于我们是做了一个。
05:08
一段时间内活跃用户的统计啊,那前面这个相当于是这个从头到尾啊,全量数据里边历史最活跃用户的统计,如果说我们加上了这个窗口的限制的话,那就相当于时效性更好了,最近这段时间内最活跃用户的统计。接下来我们在代码里面做一个具体的实现。接下来我们就直接在。Top n example这个文件里边,这段代码里边继续去写当前窗口top n的实现,啊,那同样也是一个table en要去写一个我们实现的是。窗口套盆。本身需求还是类似的啊统计。一段。
06:01
时间内的。活跃用户。我们这里是前两名。同样还是TOP2,好,那接下来这里这个CQ的话写起来应该跟之前是差不多的,这个我们自然是能够想到整体的结构跟之前其实是差不多的啊,所以甚至我们可以直接把之前的这一部分。CQ先抄过来,我们看一下哪里需要去做更改,简单来看的话,很显然,呃,我们现在想要这个user,然后CT number这些内容,其实我们都是需要,当然了应该还要有一个对应的窗口的信息才好啊,那所以呃,后边我们再看啊,窗口的信息可能我们使用当前的Windows start或者window end去做一个表示。然后接下来呢,From啊,这这里要有一个子查询,必须得有这样的一个子查询,然后才能做number的筛选,里边是要有number这样一个聚合计算的,我们接下来还是select,然后number括号over over,做一个开窗函数,这个开窗函数呢,同样还是orderby death。只不过前面就要。
07:23
新增加一个。Petition败了。我们需要去做一个分组,那当前这个分组是按照什么分呢?诶,这个是按照窗口去分,而当前窗口top喷N的写法呢,必须把当前的Windows start和window and2个字段都写到这里派后面。作为当前这个分区分组的K就是固定写法啊,同样也是当前CQ要求我们必须这么写它才能解析成这当前我们要做的是一个window top,所以这也是固定写法,只能这么去做。然后接下来from from应该也就是我们想要得到的,包含了用户以及它的访问次数,CT,还有,呃,当前还没有number,但是当前应该要有。
08:20
Win等相关的信息,所以当前其实是后边的这个子查询,这就更麻烦一点了啊,那干脆我们把这个子查询单独拿出来。放到前面来做一个,来来做一个单独的实现吧,这样会明显一点,我们把这个叫做sub。这个query首先整个的架构。其实还是类似的。我们可以直接放在这里,那就是select user,然后'。Urls CT,然后另外还应该有两个字段。
09:01
因为后边我们BY需要Windows start和window呀,诶,那当然这个子查询必须提取出来字段有这两个window。Start。Window and。然后接下来当然就是from了,呃,现在要做的这个没有这么简单。因为接下来我们其实是一个窗口聚合,窗口聚合的结果,然后再放到当前的这一个over开窗函数里边来,这样的话我们就可以统计出对应的top n了,所以本质上跟之前的一般的top。是一样的,只不过就是我们当前这个子查询,我们基于哪张表去进行筛选,这里边要基于的是一个窗口聚合查询的结果表啊,那所以前面这一部分,那就是刚好就是我们前面所说的窗口聚合查询的这个过程了,Table。
10:03
因为本身是一个表函数嘛,里边的话那就是。当前一个滚动窗口,那叫tbo。里面的话,哎,这就需要了。Table鉴定一出来,我们当前是click table。然后第二个字段,Script。里面包含了当前的属性时间,属性字段,我们定义的是叫做ET。然后接下来。另外还应该有一个interval。对应的一个定义啊,那比方说我们是这个,呃,如果要是定义一小时的话,那就是一小时,如果我们现在是十秒钟的话,那当然就是10SECOND。窗口定义好了,那后边当然就还应该是。这里就不需要了。还需要有group的话,我们现在要的是user以及。
11:06
Start和window。当前。窗口TF这种聚合方式的一个写法,先把这个子查询写在这里。然后接下来呢,当然from我们这里就干脆可以把。这样一个子查询加在这里了。Sub query,所有的这一段直接添加在当前的这个括号里面,这样我们就实现了整个window泡喷的一个查询过程。那这个query执行完毕之后,应该要得到一个新的表。我们可以把它叫做。Window top。Or table?啊,那最后同样的我们这里也做一个对应的转换成流,然后进行打印输出,那当前的这个window top,这里边涉及到一个问题是window top是不是也必须要to change streamam呢?那还是那个标准,关键是要看当前的结果表里边这张动态表有没有更新操作。
12:22
好,那我们看当前是把这个所有的语句都写到一个CQ里边,一个嵌套查询的过程,那其实基于最初的。这张数据表我们的click table里边所有的数据,每插入一行数据,最后我们要进行开窗去和统计,得到每一个窗口内。排名第一的是谁?排名第二的是谁?我们想到最终得到的这个结果是不是就是固定的啊,所以这个结果呢,直接写入到最终的结果表里边,只做一次插入,只是每一个窗口输出的结果有可能是多行数据,但是它只是做一次插入,插入进去之后就再也不会更改。
13:11
所以我们当前其实没有必要非要to,也是可以。我们把它拿进来,然后做一个print打印。当前是window top的一个输出结果。当然了,为了看的更加的明显,我们可以把上面这一部分。直接住掉。接下来运行一下,看一看效果怎么样。我们可以看到当前输出了对应的结果只有四条数据,而且都是加I,为什么这里只有加I呢?哎,那其实就是因为当前的数据里边每一个。窗口对应的输出结果,他的top n都是固定的输出一次再也不会改。
14:05
那如果说我们这里还希望得到窗口对应的信息的话,那其实也很简单,我们就在最后select的时候把它都提取出来不就完了吗?因为之前我们这个里面得到的是有窗口的对应信息的,所以我们这里可以直接简单的再增加一个。就可以了。重新运行一下就可以看到后边可以明确的告诉我们当前是哪个窗口得到的前两名。这样的话,我们看的就更加清晰,零到十秒第一个窗口里边啊,排名第一的是Bob。访问了六次,排名第二个是Mary,访问了两次,而十到20秒第二个窗口里排名第一的还是Bob,他访问了两次,而Mary只有一次访问排名第二。这从我们的输入数据里边可以非常明显的看到,对应的这个结果可以很容易的分析出到底是怎么回事儿。
15:05
这就是关于窗口泡喷的用法。所以我们会发现在实际的生产应用场景里边,所有的这些聚合方式都可以非常灵活的结合起来。那top n呢?这是当前flink底层Li CQ对它有特殊优化的一种固定用法,我们当前就是这样去使用。
我来说两句