天天看點

百萬級分組大報表開發與呈現

在《

秒級展現的百萬級大清單報表怎麼做

》中,我們介紹了無論 RDB 還是非 RDB,潤乾報表都能夠通過異步線程實作秒級海量大清單報表(以下簡稱:大報表)。實際業務中,除了查詢明細,有時還要展現全量彙總資料,或者查詢分組明細和計算分組彙總。本文就将介紹這些帶有彙總和分組的大報表的開發方法。

帶彙總的大報表

       在大報表中計算彙總值與正常報表基于報表内資料進行的彙總不同,大報表由于采用異步線程,是以無法通過報表内資料進行彙總(因為每次隻能取到部分資料),隻能在資料處理階段計算彙總值并交給報表呈現。

我們還是使用《秒級展現的百萬級大清單報表怎麼做》中 SQL 源大報表的例子,現在需要在每頁最後一行顯示訂單彙總情況(訂單數量、訂單總額、運費總額)。

百萬級分組大報表開發與呈現

制作報表模闆

       增加一個資料集 ds2 計算彙總值:

百萬級分組大報表開發與呈現

 報表中最後一行引入 ds2 彙總值進行呈現,這裡為了每頁都包含彙總資料,設定最後一行屬性為報表尾。

百萬級分組大報表開發與呈現

   當然,帶有彙總的大報表性能跟計算彙總值的 SQL 執行效率強相關,是以可能會發現帶有彙總的大報表要比單純查詢明細慢一些。

分組大報表

       實際業務中,簡單呈現大報表清單往往還不夠,有時還需要對海量資料進行分組,呈現彙總及明細情況。下面,我們就以訂單資料為例,查詢一下按地區分組的明細及訂單金額彙總。

需求分析

       首先,需要呈現分組明細的報表無法在資料源端進行聚合,例如通過 SQL 聚合後就不包含分組明細了,除非再查詢一次進行拼接,但查詢兩次顯然會嚴重影響性能。是以我們需要盡量将明細資料讀出後在應用端進行分組聚合。

   那問題就來了,由于海量資料要通過分批讀取的方法進行呈現,如何保證讀取的每批分組資料是完整的?如果分組資料不完整,分組聚合的結果顯然也就不正确了。是以,除了要保證能在應用端實作聚合,還要保證批量讀取資料時分組資料的完整性。

   下面就是潤乾報表結合集算器(資料集)實作分組大報表的過程。

報表資料準備

       我們需要編寫集算器 SPL 腳本進行資料準備。這裡,我們要編寫兩個 SPL 腳本,分别實作:查詢分組明細并計算彙總,以及通過遊标分批為報表傳回結果集。

SPL 腳本 1:group-detail.dfx

設定腳本參數:

百萬級分組大報表開發與呈現

編寫 SPL 腳本:

百萬級分組大報表開發與呈現

SPL 解析:

1、 A2 查詢資料庫,SQL 中指定按照分組字段(貨主地區)排序,以便後續可以每次取出整個分組進行彙總。為此需要在排序字段上建立索引,避免全表排序時間過長。

2、 A3 循環遊标,以貨主地區為标記,保證每次讀取的記錄數為一個地區資料

3、 B4 增加标志位,用于後續報表展現中突出彙總行。标志為 0 時表示是明細記錄

4、 B5 針對每個分組進行彙總

5、 B6 将分組值追加到明細記錄中,标志設為 1,表示是彙總記錄

6、 B7 傳回分組明細和彙總集合。注意這裡 return 寫在循環内,是以會多次傳回分組集合

關于 for cs,n;x 用法

在集算器 SPL 腳本中,for cs,n;x 表示針對遊标 cs 通過循環周遊資料,每輪從遊标讀取 n 條記錄或者直到記錄中的 x 發生變化,循環全部結束後關閉遊标。大資料量的分組取數是這種循環的常用之處。如果省略了 n 和 x,那就簡單地傳回遊标中所有資料并關閉遊标。函數的具體說明可以參考:

http://doc.raqsoft.com.cn/esproc/func/forcsnx.html

   當大資料集按照分組字段有序時,這種取數方式每次可以讀取一個完整分組到記憶體中參與計算,不過這時仍然要求分組不能很大(記憶體能裝下)。而在金融和電信行業中,經常要基于單使用者做資料分析,也就是按使用者分組,而每個使用者的流水記錄規模又較大,正常的拆分方法作起來十分複雜。而通過集算器就可以很好地解決這類問題了。

SPL 腳本 2:main.dfx

百萬級分組大報表開發與呈現
百萬級分組大報表開發與呈現

前一個 SPL 腳本 group-detail.dfx 解決了分組查詢明細并彙總計算的問題。這個腳本 main.dfx 則可以分批次取數并提供給潤乾報表,進而實作異步大報表呈現。腳本中 A1 通過 cursor 函數直接調用前一腳本生成遊标,由 A2 将遊标傳回給報表。

關于 cursor() 函數

       使用 cursor 函數調用 SPL 腳本生成遊标時,被調用的 SPL 腳本可以有多個傳回結果集(例如在 for 循環中的多個 return),而遊标取數(fetch)時可以依次使用多個 return 結果,無需等待所有結果集都準備好再使用,原理如下圖所示。函數的具體說明可以參考:

http://doc.raqsoft.com.cn/esproc/func/cursordfx.html
百萬級分組大報表開發與呈現

結合大報表使用 cursor() 函數運作原理

設計報表模闆

設定報表參數,查詢起止日期:

百萬級分組大報表開發與呈現

設定資料集引用 main.dfx 并傳遞日期參數:

百萬級分組大報表開發與呈現

   按照大報表模闆設計思路,編寫表達式

百萬級分組大報表開發與呈現

為了将彙總行高亮顯示出來,這裡利用了資料準備階段增加的标志位 flag 列,當 flag 值為 1 的時候代表該行為彙總行,設定背景色表達式:if(A3==1,-3355444)

設定大資料集

百萬級分組大報表開發與呈現

釋出到 WEB

       将做好的模闆釋出到 WEB 端,效果如下:

百萬級分組大報表開發與呈現

當然,标志位 flag 列也可以設定為隐藏。

效果調整

       調整報表模闆,将标志位 flag 列隐藏,并設定 B3 格的擴充屬性 同值合并為“縱向合并”

百萬級分組大報表開發與呈現

展現時分組列則帶有合并格的效果:

百萬級分組大報表開發與呈現

注意事項

       在《秒級展現的百萬級大清單報表怎麼做》中,我們提示了大報表不要全表排序,也不适合高并發場景。除此以外,對于帶有分組彙總和明細的大報表還應該注意:

單個分組不宜過大

       由于計算分組明細和彙總值時需要将某一個分組資料全部加載到記憶體中進行計算,是以分組相對記憶體容量不宜過大,進而確定單個分組資料能進行全記憶體計算。

作者:lisongbo

連結:

http://c.raqsoft.com.cn/article/1536328795758

來源:乾學院

著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。