潤乾報表實現中間資料外接

xiaohuihui發表於2019-12-27

絕大多數報表專案的資料庫中,除了支撐系統執行的業務資料表之外,實際業務還可能產生很多中間表。業務資料表是報表系統的核心和基礎,是支援報表系統執行的持久化資料層,例如:銷售報表系統中的訂單、客戶、產品等。而中間表大多則是計算和生成報表的中間計算過程,一般只支援臨時性或者區域性性的需求,而且名字經常是五花八門,不利管理和維護。

按道理說,在一個“健康”的業務系統中,業務資料表應該佔大多數,報表中間表應該只佔少數。但實際情況卻恰恰相反,在有些執行了較長時間的報表系統中,常常可以看到報表中間表達到幾千個或者更多,而業務資料表只有一兩百個。

對於關係型資料庫來說,其綜合成本與資料表的數量、資料量密切相關。資料庫中報表中間表過多會導致以下問題:

表越多,資料量越大,資料庫的負載壓力就越大,這會直接引起效能下降。

資料庫壓力達到一定程度就必須擴容,專案成本會增加不少。

關聯式資料庫是扁平結構,不能以多級目錄的形式來管理資料,因此只適合管理數量較少的表。而中間表命名隨意,非常容易形成大量意義混淆的表名,可管理性差。

表多、資料量大,直接造成資料庫管理和維護成本的增加。

那麼,該如何減少報表開發中的資料庫中間表呢?分庫,是目前報表專案中解決資料庫中間冗餘資料常見的做法。但是,不管是將資料庫分成多個,抑或是構建專門的資料倉儲,本質上還是用傳統關係型資料庫來承載中間資料,因此,上邊所說的各種問題依然存在,得不到本質的解決。

因此,最理想的思路就是,能否將中間資料從資料庫中移出來呢?比如小結果集直接計算後返回,大結果集放到硬碟檔案上?如果能這樣做,好處非常明顯:

1、降低了資料庫的壓力,讓報表系統執行更快。

資料庫不必因為報表中間表的原因而擴容,可以降低專案成本。

檔案可以按照業務種類、模組關係、時間順序進行多級目錄管理,可管理性高。

資料表少了,資料庫管理和維護自然變得容易,運維成本明顯降低。

但是,中間資料外接的做法對於多數程式設計師來說,只是個美好的願望而已。他們不是“不願”把中間表放到資料庫外,而是“不能”放到庫外。因為,資料一旦離開了資料庫,就失去了“計算能力”。例如:某專案中產生了一箇中間表 temp2009sales,存放 2009 年客戶 - 訂單資料,並已按照客戶分組。如果資料在資料庫中,對這個表按照客戶排序很容易實現,但是匯出到文字檔案後就沒辦法排序了,因為檔案本身沒有計算能力。

所以,中間資料外接的關鍵就在於能否實現基於檔案的資料計算能力,特別是通用的計算能力。如果採用潤乾集算器,其集算引擎可以使檔案擁有計算能力,從而實現複雜計算與報表展現的徹底分離,完美實現程式設計師“把報表中間資料從資料庫中移出來”的願望。下圖顯示了引入潤乾報表和集算引擎前後的報表系統結構對比:

imagepng

由於潤乾報表能夠很好地支援異構資料來源,上面提到的中間資料檔案 temp2009sales 雖然已經放到了庫外,但是依然可以和資料庫中其他的業務表進行關聯計算,用於最終生成報表,例如下圖這張“某公司客戶累計銷售額與去年全年銷售額對比報表”:

imagepng

這張報表中,客戶、訂單數、銷售額都是直接從資料庫的當年資料計算得到的,即 2010 年 1 月 -10 月的資料;2009 年全年的訂單數、銷售額則是從檔案系統中的 temp2009sales.b 檔案中讀取;而“銷售額 / 去年銷售額”則是利用今年和去年的資料計算得到的。

下面我們就重點看一下這個報表的開發過程。(報表上部的查詢按鈕是集算報表提供的“引數模板”功能,具體做法參見教程,這裡不再贅述。)

1、資料檔案準備:

提前用集算器從資料庫中讀取 2009 年的銷售資料,計算好之後,以集算器的二進位制編碼方式匯出到檔案 temp2009sales.b 中。中間資料製作好後,資料庫中 2009 年的資料就可以移除了,釋放寶貴的資料庫空間。

2、編寫集算器指令碼 salesProportion.dfx:

其中指令碼中用到引數:argyear(要查詢的年份),argmonth(要查詢的月份)。

A
1 =connect(“db”)
2 =A1.query(“select client,count(orderid) c,sum(amount) s from sales where year(orderdate)=? and month(orderdate)<=? group by client”,argyear,argmonth)
3 =file(“D:/files/salesproportion /temp”+string(argyear-1)+“sales.b”).import@b()
4 =A3.align(A2:CLIENT,CLIENT)
5 =A2.new(CLIENT,C:COUNT,S:TOTAl,A4(#).C:lastCOUNT,A4(#).S:lastTOTAL,S/A4(#).S:PROPORTION)
6 result A5

程式碼說明:

A1:連線預先配置好的資料來源 demo。

A2:從資料庫中計算取出要查詢的年份訂單數、銷售額。

A3:從前一年的資料檔案中取出資料。

A4:將 A3 中的資料按照 A2 中的 CLIENT 欄位對齊,A2 中有但 A3 中沒有的則補空行。

A5:利用 A2 來生成新的序表。其中增加了 A4 的對應行資料,比如 A4(#).C:lastCOUNT 就是 A4 的對應行中取出 C 欄位,其中 #是 A2 的當前行號。

A6:關閉資料庫連線。

A7:向報表返回結果集。

3、在潤乾報表中定義報表引數(argyear、argmonth)和計算資料集:

imagepng

上圖中,引數名是指 dfx 定義的引數名稱,引數值是指報表提交給集算引擎的值。配置好後,就會將報表的兩個引數的值傳遞給集算器的同名引數。

4、設計報表,如下圖:

imagepng

輸入引數計算後,即可得到前面希望的報表了。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900830/viewspace-2671014/,如需轉載,請註明出處,否則將追究法律責任。

相關文章