您好,登錄后才能下訂單哦!
在《秒級(jí)展現(xiàn)的百萬(wàn)級(jí)大清單報(bào)表怎么做》中,我們介紹了無(wú)論 RDB 還是非 RDB,潤(rùn)乾報(bào)表都能夠通過(guò)異步線程實(shí)現(xiàn)秒級(jí)海量大清單報(bào)表(以下簡(jiǎn)稱:大報(bào)表)。實(shí)際業(yè)務(wù)中,除了查詢明細(xì),有時(shí)還要展現(xiàn)全量匯總數(shù)據(jù),或者查詢分組明細(xì)和計(jì)算分組匯總。本文就將介紹這些帶有匯總和分組的大報(bào)表的開(kāi)發(fā)方法。
在大報(bào)表中計(jì)算匯總值與常規(guī)報(bào)表基于報(bào)表內(nèi)數(shù)據(jù)進(jìn)行的匯總不同,大報(bào)表由于采用異步線程,因此無(wú)法通過(guò)報(bào)表內(nèi)數(shù)據(jù)進(jìn)行匯總(因?yàn)槊看沃荒苋〉讲糠謹(jǐn)?shù)據(jù)),只能在數(shù)據(jù)處理階段計(jì)算匯總值并交給報(bào)表呈現(xiàn)。
我們還是使用《秒級(jí)展現(xiàn)的百萬(wàn)級(jí)大清單報(bào)表怎么做》中 SQL 源大報(bào)表的例子,現(xiàn)在需要在每頁(yè)最后一行顯示訂單匯總情況(訂單數(shù)量、訂單總額、運(yùn)費(fèi)總額)。
增加一個(gè)數(shù)據(jù)集 ds2 計(jì)算匯總值:
報(bào)表中最后一行引入 ds2 匯總值進(jìn)行呈現(xiàn),這里為了每頁(yè)都包含匯總數(shù)據(jù),設(shè)置最后一行屬性為報(bào)表尾。
當(dāng)然,帶有匯總的大報(bào)表性能跟計(jì)算匯總值的 SQL 執(zhí)行效率強(qiáng)相關(guān),所以可能會(huì)發(fā)現(xiàn)帶有匯總的大報(bào)表要比單純查詢明細(xì)慢一些。
實(shí)際業(yè)務(wù)中,簡(jiǎn)單呈現(xiàn)大報(bào)表清單往往還不夠,有時(shí)還需要對(duì)海量數(shù)據(jù)進(jìn)行分組,呈現(xiàn)匯總及明細(xì)情況。下面,我們就以訂單數(shù)據(jù)為例,查詢一下按地區(qū)分組的明細(xì)及訂單金額匯總。
首先,需要呈現(xiàn)分組明細(xì)的報(bào)表無(wú)法在數(shù)據(jù)源端進(jìn)行聚合,例如通過(guò) SQL 聚合后就不包含分組明細(xì)了,除非再查詢一次進(jìn)行拼接,但查詢兩次顯然會(huì)嚴(yán)重影響性能。因此我們需要盡量將明細(xì)數(shù)據(jù)讀出后在應(yīng)用端進(jìn)行分組聚合。
那問(wèn)題就來(lái)了,由于海量數(shù)據(jù)要通過(guò)分批讀取的方法進(jìn)行呈現(xiàn),如何保證讀取的每批分組數(shù)據(jù)是完整的?如果分組數(shù)據(jù)不完整,分組聚合的結(jié)果顯然也就不正確了。因此,除了要保證能在應(yīng)用端實(shí)現(xiàn)聚合,還要保證批量讀取數(shù)據(jù)時(shí)分組數(shù)據(jù)的完整性。
下面就是潤(rùn)乾報(bào)表結(jié)合集算器(數(shù)據(jù)集)實(shí)現(xiàn)分組大報(bào)表的過(guò)程。
我們需要編寫集算器 SPL 腳本進(jìn)行數(shù)據(jù)準(zhǔn)備。這里,我們要編寫兩個(gè) SPL 腳本,分別實(shí)現(xiàn):查詢分組明細(xì)并計(jì)算匯總,以及通過(guò)游標(biāo)分批為報(bào)表返回結(jié)果集。
設(shè)置腳本參數(shù):
編寫 SPL 腳本:
A | B | C | |
1 | =connect("db") | ||
2 | =A1.cursor@x(“select 貨主地區(qū), 訂單 ID, 客戶 ID, 訂購(gòu)日期, 運(yùn)貨費(fèi), 訂單金額 from 訂單 where 訂購(gòu)日期 >=? and 訂購(gòu)日期 <=? order by 貨主地區(qū)”,begin,end) | /建立數(shù)據(jù)庫(kù)游標(biāo)查詢訂單數(shù)據(jù),并按地區(qū)排序 | |
3 | for A2; 貨主地區(qū) | /按地區(qū)分組讀取數(shù)據(jù) | |
4 | =A3.derive(0:flag) | /增加標(biāo)志位 | |
5 | =B4.sum(訂單金額) | /分組匯總 | |
6 | >B4.insert(0,null,null,null,null,"訂單金額小計(jì):",B5,1) | /匯總值添加到明細(xì)數(shù)據(jù)中 | |
7 | return B4 | /返回明細(xì)及分組結(jié)果 |
SPL 解析:
1、 A2 查詢數(shù)據(jù)庫(kù),SQL 中指定按照分組字段(貨主地區(qū))排序,以便后續(xù)可以每次取出整個(gè)分組進(jìn)行匯總。為此需要在排序字段上建立索引,避免全表排序時(shí)間過(guò)長(zhǎng)。
2、 A3 循環(huán)游標(biāo),以貨主地區(qū)為標(biāo)記,保證每次讀取的記錄數(shù)為一個(gè)地區(qū)數(shù)據(jù)
3、 B4 增加標(biāo)志位,用于后續(xù)報(bào)表展現(xiàn)中突出匯總行。標(biāo)志為 0 時(shí)表示是明細(xì)記錄
4、 B5 針對(duì)每個(gè)分組進(jìn)行匯總
5、 B6 將分組值追加到明細(xì)記錄中,標(biāo)志設(shè)為 1,表示是匯總記錄
6、 B7 返回分組明細(xì)和匯總集合。注意這里 return 寫在循環(huán)內(nèi),因此會(huì)多次返回分組集合
在集算器 SPL 腳本中,for cs,n;x 表示針對(duì)游標(biāo) cs 通過(guò)循環(huán)遍歷數(shù)據(jù),每輪從游標(biāo)讀取 n 條記錄或者直到記錄中的 x 發(fā)生變化,循環(huán)全部結(jié)束后關(guān)閉游標(biāo)。大數(shù)據(jù)量的分組取數(shù)是這種循環(huán)的常用之處。如果省略了 n 和 x,那就簡(jiǎn)單地返回游標(biāo)中所有數(shù)據(jù)并關(guān)閉游標(biāo)。函數(shù)的具體說(shuō)明可以參考:http://doc.raqsoft.com.cn/esproc/func/forcsnx.html
當(dāng)大數(shù)據(jù)集按照分組字段有序時(shí),這種取數(shù)方式每次可以讀取一個(gè)完整分組到內(nèi)存中參與計(jì)算,不過(guò)這時(shí)仍然要求分組不能很大(內(nèi)存能裝下)。而在金融和電信行業(yè)中,經(jīng)常要基于單用戶做數(shù)據(jù)分析,也就是按用戶分組,而每個(gè)用戶的流水記錄規(guī)模又較大,常規(guī)的拆分方法作起來(lái)十分復(fù)雜。而通過(guò)集算器就可以很好地解決這類問(wèn)題了。
設(shè)置腳本參數(shù):
編寫 SPL 腳本:
A | B | |
1 | =cursor("group-detail.dfx",begin,end) | /調(diào)用 dfx 生成游標(biāo) |
2 | return A1 | /為報(bào)表返回游標(biāo) |
前一個(gè) SPL 腳本 group-detail.dfx 解決了分組查詢明細(xì)并匯總計(jì)算的問(wèn)題。這個(gè)腳本 main.dfx 則可以分批次取數(shù)并提供給潤(rùn)乾報(bào)表,從而實(shí)現(xiàn)異步大報(bào)表呈現(xiàn)。腳本中 A1 通過(guò) cursor 函數(shù)直接調(diào)用前一腳本生成游標(biāo),由 A2 將游標(biāo)返回給報(bào)表。
使用 cursor 函數(shù)調(diào)用 SPL 腳本生成游標(biāo)時(shí),被調(diào)用的 SPL 腳本可以有多個(gè)返回結(jié)果集(例如在 for 循環(huán)中的多個(gè) return),而游標(biāo)取數(shù)(fetch)時(shí)可以依次使用多個(gè) return 結(jié)果,無(wú)需等待所有結(jié)果集都準(zhǔn)備好再使用,原理如下圖所示。函數(shù)的具體說(shuō)明可以參考:http://doc.raqsoft.com.cn/esproc/func/cursordfx.html
結(jié)合大報(bào)表使用 cursor() 函數(shù)運(yùn)行原理
設(shè)置報(bào)表參數(shù),查詢起止日期:
設(shè)置數(shù)據(jù)集引用 main.dfx 并傳遞日期參數(shù):
按照大報(bào)表模板設(shè)計(jì)思路,編寫表達(dá)式
為了將匯總行高亮顯示出來(lái),這里利用了數(shù)據(jù)準(zhǔn)備階段增加的標(biāo)志位 flag 列,當(dāng) flag 值為 1 的時(shí)候代表該行為匯總行,設(shè)置背景色表達(dá)式:if(A3==1,-3355444)
設(shè)置大數(shù)據(jù)集
將做好的模板發(fā)布到 WEB 端,效果如下:
當(dāng)然,標(biāo)志位 flag 列也可以設(shè)置為隱藏。
調(diào)整報(bào)表模板,將標(biāo)志位 flag 列隱藏,并設(shè)置 B3 格的擴(kuò)展屬性 同值合并為“縱向合并”
展現(xiàn)時(shí)分組列則帶有合并格的效果:
在《秒級(jí)展現(xiàn)的百萬(wàn)級(jí)大清單報(bào)表怎么做》中,我們提示了大報(bào)表不要全表排序,也不適合高并發(fā)場(chǎng)景。除此以外,對(duì)于帶有分組匯總和明細(xì)的大報(bào)表還應(yīng)該注意:
由于計(jì)算分組明細(xì)和匯總值時(shí)需要將某一個(gè)分組數(shù)據(jù)全部加載到內(nèi)存中進(jìn)行計(jì)算,因此分組相對(duì)內(nèi)存容量不宜過(guò)大,從而確保單個(gè)分組數(shù)據(jù)能進(jìn)行全內(nèi)存計(jì)算。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。