溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SPL 分組優(yōu)化技巧

發(fā)布時間:2020-08-06 15:40:33 來源:網絡 閱讀:156 作者:raqsoft 欄目:大數據

1.????? 常規(guī)分組

當分組聚合的結果集不大時,可以使用groups。例如有學生成績表存儲在集文件中,表結構如下:

Scores
class
studentID
subject
score
……

?

現在計算每個學生的總分數:


A
1=file("scores.btx").import@b()
2=A1.groups(studentID; ? sum(score):TotalScore)

A1:成績表的數據裝入內存。

A2:按照studentID字段分組,計算總分。

?

如果成績表數據太大,無法裝入內存,則可以用游標方式:


A
1=file("scores.btx").cursor@b()
2=A1.groups(studentID; ? sum(score):TotalScore)

A1:得到成績表的游標。

A2:按照studentID字段分組,計算總分。

?

當成績表記錄很多,分組計算的結果集很大時,就要使用groupx:


A
1=file("scores.btx").cursor@b()
2=A1.groupx(studentID; ? sum(score):TotalScore;10000)

A1:得到成績表的游標。

A2:按照studentID字段分組,計算總分。

groupx的最后一個參數是緩沖區(qū)行數,也就是內存里能夠一次處理的記錄條數,這里指定為10000,實際使用時要根據自己的情況進行調整。

2.????? 有序分組

2.1.????? 前半有序

當數據對分組字段有序時,可以使用groups@o。如上例中,當成績表對studentID字段有序時,就可以加上選項o:


A
1=file("scores.btx").import@b()
2=A1.groups@o(studentID; sum(score):TotalScore)

?

如果成績表太大,無法裝入內存,可以使用游標:


A
1=file("scores.btx").cursor@b()
2=A1.groups@o(studentID; sum(score):TotalScore)

?

同樣,如果有序分組的結果集很大,就不能用groups,這時要使用group:


A
1=file("scores.btx").cursor@b()
2=A1.group(studentID; sum(score):TotalScore)

group的返回是游標,這一點跟groups不一樣。

2.2.????? 后半有序

?“后半”有序是指:要分組的表 T 已經對字段a,b有序,現在我們要將表T按字段b進行分組。例如有保存銷售記錄的集文件sale.btx,表結構如下:

Sales
date
employeeID
amount
……

銷售表對字段date,employeeID有序,現在要計算每個員工的銷售總額,對employeeID字段做分組,這時常規(guī)分組會計算hash,但這種后半有序的情況可以使用groups@h,看一下實現:


A
1=file("sale.btx").import@b()
2=A1.groups@h(employeeID; ? sum(amount):TotalAmount)

如果銷售表太大,無法裝入內存,可以使用游標:


A
1=file("sale.btx").cursor@b()
2=A1.groups@h(employeeID; ? sum(amount):TotalAmount)

?

3.????? 序號分組

當分組表達式的結果是序號的時候,可以使用groups@n。仍然使用上例的銷售表,現在要計算統(tǒng)計每個月的銷售額,實現是這樣的:


A
1=file("sale.btx").cursor@b()
2=A1.groups@n0(month(date):MONTH;sum(amount): ? TotalAmount)

A1:得到銷售表的游標。

A2:把date字段轉換為月份,計算每個月的銷售總額;如果存在date字段是null的情況,則要加上選項@0。

?

使用@n之后,會依據序號去分組,而不用再計算HASH,所以要比不帶@n時快。

使用3億條數據測試,本案例實際測試結果:

耗時(秒)
 有 @n沒有 @n
3949

4.????? 過濾拆分

過濾拆分是指根據條件分組,滿足條件和不滿足條件的分成兩個集。使用select可以做到這種拆分,但是要遍歷兩次,即一次select(條件true),和一次select(條件false)。

而使用group和align只需要遍歷一次。以上面成績表為例,現在要把成績及格的和不及格的分成兩組,看一下group的實現:


A
1=file("scores.btx").import@b()
2=A1.group(score>=60)

?

需要注意的是,使用group過濾拆分的結果不一定是兩個集,有可能結果只有一個集,如本例中,有可能出現成績都大于60的情況。這時候需要判斷一下結果集的個數,或者使用align,因為align的結果肯定是兩個集,沒有符合條件的記錄,也會產生一個空集。來看一下align的實現:

?

?


A
1=file("scores.btx").import@b()
2=A1.align@a([true,false],score>=60)

?

如果想在過濾拆分中把不滿足的寫進文件,可以使用select(x;file),看一下實現:


A
1=file("scores.btx").cursor@b()
2=A1.select (score>=60;file(“Fail.btx”))
3=A2.fetch()

執(zhí)行完成后,A3里是成績及格的,不及格的會保存到集文件Fail.btx。

?

如果要拆分為多個集,可以使用groupn。例如要把成績分為優(yōu)秀、良好、及格和不及格這些集合,可以這樣實現:


A
1=file("scores.btx").cursor@b()
2=[file(“Excellent.btx”), file(“Good.btx”), ? file(“Pass.btx”), file(“Fail.btx”)]
3=A1.groupn(if(score>=90:1, ? score>=80:2, score>=60:3,4);A2)
4=A3.fetch()

5.????? 組內TopN

top也可以用于group中,例如計算每個部門里薪水的最大值:


A
1=file("employee.btx").cursor@b()
2=A1.groups(dept;top(-1,salary):MaxSalary)

A1:得到員工表的游標。

A2:按照dept字段分組,組內再求最高薪水值,命名為topSalary。

?

A2執(zhí)行結果的MaxSalary字段是數值,如果想查詢薪水最高的員工的信息,可以寫成這樣:


A
1=file("employee.btx").cursor@b()
2=A1.groups(dept;top(-1;salary):MaxSalary)

?

top不僅可以返回最大值,還可以得到前n個最靠前的值,這時把1寫成n即可。例如計算每個部門里薪水排前三名的員工的信息:


A
1=file("employee.btx").cursor@b()
2=A1.groups(dept;top(-3;salary):topSalary)

?

6.????? 并行

使用groups進行分組計算時,還可以采取并行方式進一步提高性能,這時要加上選項@m。

如上面例中,計算每個員工的銷售總額,看一下并行方式的實現:


A
1=file("sale.btx").import@m()
2=A1.groups@m(employeeID; sum(amount):TotalAmount)

?

如果數據太大,無法裝入內存,可以使用多路游標:


A
1=file("sale.btx").cursor@mb()
2=A1.groups@m(employeeID; sum(amount):TotalAmount)


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI