1. 程式人生 > >Esper學習筆記五:EPL語法(3)

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