Esper学习笔记五:EPL语法(3)

1.Aggregation

类似于SQL中的聚合函数,EPL中聚合函数格式如下:

aggregate_function([all|distinct] expression)

aggregate_function就是聚合函数的名字,比如avg,sum等。expression通常是事件流的某个属性,也可以是不同事件流的多个属性,或者是属性和常量、函数之间的运算。

// 查询最新5秒的Apple的平均价格
select avg(price) as aPrice from Apple.win:time(5 sec)
 
// 查询最新10个Apple的价格总和的两倍
select sum(price*2) as sPrice from Apple.win:length(10)
 
// 查询最新10个Apple的价格,并用函数计算后再算平均值
select avg(Compute.getResult(price)) from Apple.win:length(10)

函数只能是静态方法,普通方法不可用。即使是事件流里包含的静态方法,也必须用“类名.方法名”的方式进行引用。

可以使用distinct关键字对expression加以约束,表示去掉expression产生的重复的值。默认情况下为all关键字,即所有的expression值都参与聚合运算。

// 查询最新5秒的Apple的平均价格
select avg(distinct price) as aPrice from Apple.win:time(5 sec)
 
// 假如:5秒内进入了三个Apple事件,price分别为2,1,2。则针对该EPL的平均值为(2+1)/2=1.5。因为有distinct的修饰,所以第二个2不参与运算,事件总数即为2,而不是3。

以上就是聚合函数的使用方法,除此之外需要注意一下几点

1.聚合函数能用于Select和Having,但是不能用于Where

2.sum,avg,media,stddev,avedev只能计算数值,至于media,stddev和avedev代表什么意思,请自行百度。

3.Esper会忽略expression为null不让参与聚合运算,但是count函数除外,即使是null也认为是一个事件。如果事件流集合中没有包含任何事件,或者包含的事件中用于聚合计算的expression都是null(比如收集5秒内进入的事件即为一个事件流集合),则所有聚合函数都返回null。

2.Group by

Group by通常配合聚合函数使用。语法和SQL基本一样,产生的效果就是以某一个或者多个字段进行分组,然后使聚合函数作用于不同组的数据。

使用group by 要注意一下几点:

1.Group by后面的内容不能包含聚合函数

2.Group by后面的内容不能是之前select子句中聚合函数修饰的属性名

3.通常情况要保证分组数量有限制,以防止内存溢出。但是如果分组分了很多,就需要使用@Hint加以控制。

group by 基本用法

// 根据color和size来对10个Apple事件进行分组计算平均price
select avg(price) as aPrice, color, size from Apple.win:length_batch(10) group by color,size

上面例子对color,size同时进行分组,及只有color和size都相同的事件进行统计平均price。

// 根据size来对10个Apple事件进行分组计算平均price和color
select avg(price) as aPrice, color, size from Apple.win:length_batch(10) group by size

只对size进行分组,只要size一样的事件都进行分组计算。

/ 根据size乘color来对10个Apple事件进行分组计算平均price
select avg(price) as aPrice, size*color from Apple.win:length_batch(10) group by size*color

group by的对象只是一个值,以相同的值进行分组,所以上面和和普通的属性字段一样,计算一个值进行分组。如果group by后面的表达式值为null,则所有为null的事件都被分为一组进行计算。

3.@Hint

@Hint是Esper中注解的其中一个它是专用于Group by的。我们平时使用Group by的时候,会遇到分组数量太多的情况。比如以时间单位进行分组,那么内存使用一定是一个大问题。因此@Hint为其设计了两个属性,用于限制Group by的生存时间,使虚拟机能及时回收内存。这两个属性分别为reclaim_group_aged和reclaim_group_freq。

reclaim_group_aged

该属性后面跟着的是正整数,以秒为单位,表示在n秒内,若分组的数据没有进行更新,则分组数据被Esper回收。

// 根据color对10秒内进入的Apple事件进行分组计算平均price,并且对5秒内没有数据更新的分组进行回收
@Hint('reclaim_group_aged=5')select avg(price) as aPrice, color from Apple.win:time(10 sec) group by color //括号内可以使单引号也可以是双引号

reclaim_group_freq

该属性后面跟着的是正整数,以秒为单位,表示每n秒清理一次分组,可清理的分组是reclaim_group_aged决定的,也就是说要使用该参数,就要配合reclaim_group_aged一起使用。

// 根据color对10秒内进入的Apple事件进行分组计算平均price。对8秒内没有数据更新的分组进行回收,回收频率每2秒回收一次
@Hint('reclaim_group_aged=8,reclaim_group_freq=2')select avg(price) as aPrice, color from Apple.win:time(10 sec) group by color

如果不使用reclaim_group_freq属性,则默认值和reclaim_group_aged的值一样,对上面来说就是回收的条件为8秒内没有数据更新,且每8秒回收一次。这样的话有可能出现这么一种情况,上一个8秒的某个分组在下一个8秒还没到达时就已经持续8秒没有数据更新了(这句话会不会有点绕?),但是必须等到回收的时间点到达时才能回收这个分组。在分组产生很快的情况下,这样的回收不及时很可能会造成内存溢出。reclaim_group_freq正是为这种情况做准备,回收的频率高一些,在一定程度上能提高内存的使用率。

4.Having

Having的用法和SQL一样,后面跟的是对聚合函数的计算结果进行过滤。Where子句不能包含聚合函数,所以就由Having来完成。

//根据name进行分组,计算8秒内price的平均值,并且排除平均price小于或等于5的事件。
@Hint('reclaim_group_aged=8,reclaim_group_freq=2')select avg(price) as p,name,age  from myEvent.win:time(8 sec) group by name having avg(price) > 5

Having后面可以跟多个判断式子,并且用and,or或者not进行连接。

//获取8秒内平均price大于4并且平均age大于27的事件记录。
select avg(price) as p,name,age  from myEvent.win:time(8 sec) having avg(price) > 4 and avg(age) > 27

5.Output

Output是EPL中非常有用的东西,用来控制Esper对事件流计算结果的输出时间和形式,可以以固定频率,也可以是某个时间点输出。

output [all | first | last | snapshot] every time_period | output_rate events

每隔指定时间输出结果

// 30分钟内,每进入一个OrderEvent,统计一次sum price,并且每60秒输出一次统计结果。
select sum(price) from OrderEvent.win:time(30 min) output snapshot every 60 seconds

指定数量事件之后,开始输出结果

// 统计20个Apple事件的sum price,并且在有5个Apple事件进入后才开始输出统计结果
select sum(price) from Apple.win:length(20) output after 5 events

指定时间之后,每隔多少时间输出一次结果。

/ 从EPL可用开始计时,经过1分钟后,每5秒输出一次当前100秒内的所有Banana的avg price(即:第一次输出在65秒时)
select avg(price) from Banana.win:time(100 sec) after 1 min snapshot every 5 sec

输出每两个事件中的第一个事件结果

select avg(price) as p,name,age  from myEvent.win:time(10 sec) output first every 2 events

输出每两个事件中的最后一个事件结果

select avg(price) as p,name,age  from myEvent.win:time(10 sec) output last every 2 events

每进入两个事件,就输出窗口内的所有事件

select avg(price) as p,name,age  from myEvent.win:time(10 sec) output snapshot every 2 events

每进入俩个事件,就输出窗口内的所有事件,并清空窗口内事件

select avg(price) as p,name,age  from myEvent.win:time(5 sec) output all every 2 events

配置定时规则,定时输出数据

// 在8点到17点这段时间内,每15分钟输出一次
select * from Fruit output at (*/15,8:17,*,*,*)

6.when

当达到指定条件时,输出之前进入引擎的所有事件。

转载:https://blog.csdn.net/luonanqin/article/details/12224303

猜你喜欢

转载自my.oschina.net/u/3100849/blog/1941650