您好,登錄后才能下訂單哦!
使用緩存可以提升報表性能是不爭的事實,一般高端報表工具都會提供報表緩存功能,可將整個報表計算結果緩存在文件系統中,以便用戶下次訪問相同參數的報表時可以快速讀取緩存結果進行展現。但有些情況下報表開發人員還希望對緩存的內容進行更準確和靈活的控制,比如緩存的不是整個報表結果而是其中一部分、緩存內容可被其它報表或程序復用,以及對不同的緩存結果設置不同的超時時間,從而應對數據量和實時性方面的不同情況。這時,一般的報表緩存就無法滿足需求了。
集算器與報表結合使用時,可以幫助開發人員靈活控制緩存內容。這里我們將開發人員在使用集算器可以靈活控制的報表緩存內容稱為可控緩存。可控緩存可以帶來更大的靈活性和好處,充分解決實際應用中的報表性能問題。下面我們就對前面提到的部分緩存、緩存復用和設置不同超時時間三個方面展開討論。
在報表開發中,有時并不希望將所有報表結果進行緩存,這樣可以避免耗費過高的緩存成本(磁盤空間和應用服務器資源開銷)。另外,當報表中的部分數據實時性要求很高,需要實時與數據庫交互進行數據查詢,那么這部分數據也不適合進行緩存。
通過集算器的可控緩存可以將變化不頻繁的中間結果緩存起來,當報表再次請求時,實時性要求高的數據仍然實時從數據庫中讀取,同時結合緩存中的非實時數據進行報表計算,得到最終報表結果集。
常規緩存方案沒有這種緩存部分結果的功能,只能設置整個報表是否進行緩存,這樣報表在涉及不同時效性數據時就會發生矛盾,而集算器實現的可控緩存顯然更加靈活,效率更高。
訂單(Orders)數據中超過 3 個月的數據就不再發生變化(冷數據)
數據結構如下:
現查詢近 6 個月的訂單明細并匯總月訂單數量和金額。
報表表樣如下:
直接從數據庫訂單表檢索 6 個月的數據實現雖然最簡單,但每次查詢都要從數據庫取全部數據顯然性能不高。可以將 3 個月以上不變的數據在初次查詢時緩存起來,而 3 個月內的數據仍然從數據庫讀取,這樣以后再查時直接讀緩存和數據庫數據來加速報表性能,可以顯著減少數據庫的計算時間和 JDBC 的傳輸時間。
集算器將根據查詢月份判斷:
如果查詢的是歷史數據第一次查詢數據庫并寫緩存,以后直接讀緩存;
如果查詢的是實時數據則每次都從數據庫讀取;
如果查詢的數據包含歷史數據和實時數據則將歷史數據寫緩存,實時數據讀取數據庫。
查詢參數為起止月份(每個月 1 日),實現中日期過濾數據均通過起止參數處理
A | B | C | |
---|---|---|---|
1 | =filePath=”/usr/report/cache/” | / 緩存目錄 | |
2 | =reportName=”orders_customer_month” | / 報表名稱,緩存使用報表名 + 參數命名 | |
3 | =elapse@m(pdate@m(now()),-3) | / 三個月前日期 | |
4 | =his_end=[end,A3].min() | / 歷史數據日期終值 | |
5 | =pdate@me(end) | / 查詢日期終值 | |
6 | =sql=”select 公司名稱 客戶, 訂單 ID, 訂購日期, 訂單金額 from 訂單, 客戶 where 訂單. 客戶 ID= 客戶. 客戶 ID and 訂購日期 >=? and 訂購日期 <=?” | ||
7 | =f=file(filePath/reportName/”=”/begin/”+”/his_end) | / 緩存文件 | |
8 | =rs=[] | / 報表結果集 | |
9 | if f.exists() | // 如果有緩存 | |
10 | =f.import@b() | / 歷史數據讀緩存 | |
11 | >rs=rs|B10 | / 緩存結果添加到結果集 | |
12 | =elapse@m(A3,1) | / 查詢數據庫起始日期 | |
13 | if B12<end | / 有實時數據查詢數據庫 | |
14 | =connect(“demo”) | ||
15 | >rs=rs|C14.query@x(sql,B12,A5) | ||
16 | return rs | ||
17 | else | // 無緩存 | |
18 | =connect(“demo”) | ||
19 | =rs=B18.query@x(sql,begin,A5) | / 全量數據讀庫 | |
20 | if begin<his_end | / 將歷史數據寫入緩存 | |
21 | =B19.select(訂購日期 >=begin && 訂購日期 <=A5) | ||
22 | >f.export@b(C21) | ||
23 | return rs |
腳本解析:
1、A1-A2 分別設置緩存目錄和報表名稱,報表名稱用于緩存文件命名
2、A3-A5 根據月份參數計算歷史數據日期、實時數據日期等
3、A6 為查詢 SQL,由于后面會重復使用,這里將其賦值給 sql 變量
4、A7 設置緩存文件,文件名為:報表名 = 緩存起始月 - 緩存終止月,如:orders_customer_month=2014-01-01+2014-04-01
5、A8 定義報表數據集變量 rs,后續讀緩存和查詢數據庫結果都會追加到 rs 中
6、A9-C16 判斷緩存(包含三個月以上數據)如果存在,則根據查詢月份讀取緩存歷史數據(B10),如果還包含實時數據則查詢數據庫(C15),結果集追加到 rs 中并為報表輸出結果(B16)
7、A17-C23 如果沒有緩存(可能是初次查詢,也可能查詢的是實時數據),則直接查詢數據庫并返回結果(B19),若查詢數據中包含歷史歷史數據,則寫緩存(C21 和 C22)
這里假定讀者已經了解集算器與報表的關系,集算器僅為報表提供數據準備,將計算結果以數據集的方式提供給報表進行呈現。集算器腳本可以被潤乾報表 5.0 及以上版本直接引用(集算器數據集);如果是其他報表工具,集算器提供了標準 JDBC 和 ODBC 接口,可以采用類似調用存儲過程的方式調用集算器腳本,詳細可以參考教程《應用集成 - 被 JAVA 調用》章節,以及《集算器與 BIRT 集成》或《集算器與 JasperReport 集成》。
以上通過舉例說明了通過集算器實現報表緩存部分結果提升報表性能的過程,這種方式可以靈活控制緩存內容,加速報表運行。此外,將結果緩存到磁盤避免了通過數據庫 JDBC 取數效率低下的問題,數據量大時尤其適用,同時由于緩存無需和數據庫交互,降低了數據庫的訪問和計算壓力,在報表加速的同時緩解了數據庫負擔。
值得注意的是,業務數據無論是否分庫都可以使用這個方式提升報表性能。
集算器實現的可控緩存可以復用,一個報表的緩存結果(部分或全部)可以被其他報表或程序讀取并使用,而不必像常規報表緩存方案那樣重復緩存同樣的結果,這同樣也會大幅度提高整體緩存的效率。
與緩存部分結果適應實時性要求的情況類似,當其他報表或程序使用某個報表的緩存結果時,只需從緩存中(一般是磁盤文件)讀取,并與報表中其他數據來源(可能是 DB、文件,或是另一個報表的緩存)進行混合運算,就能得到報表需要的結果集。而常規的報表緩存以報表模板為單位進行緩存,彼此無法復用,在造成資源浪費之外還會增加一定的性能開銷。
上例中,如果另一張報表希望按客戶來匯總訂單情況:
報表表樣如下:
熟悉報表的開發者都知道,這兩張報表只是分組方式不同,數據源是完全一樣的,這樣我們就還可以使用上面的代碼獲取數據源,并且生成和訪問緩存,這兩張報表就可以共用緩存了。
我們都知道緩存一定都會有超時時間,超過時間后的緩存就會因為失效而被清除,報表再訪問時需要重新生成緩存文件。
一般報表工具的緩存超時時間會在配置文件中設置,如 3600s 或 7200s,這種設置有時作用于單張報表的所有參數,有時甚至作用于所有報表,換句話說,整個報表甚至整個系統必須使用同樣的設置。
顯然,這種做法的性能并不高,很難兼顧不同更新頻率的數據。如果能夠針對不同的報表場景設置不同的超時時間,那樣會更加有效。例如,針對大量歷史數據進行查詢的報表,由于歷史數據的變化不大,我們希望報表的緩存結果可以保存較長時間,以便每次查詢時都能從緩存中快速讀取結果;而針對數據變化頻繁,實時性要求較高的報表則希望超時時間較短,以便充分滿足數據的實時性要求。
集算器實現的可控緩存允許開發人員針對不同的報表需求設置不同的超時時間,以應對上述提到的報表場景,例如可以在第一個例子中增加超時設置。這種做法提供了更高的靈活性,使得報表緩存達到真正意義上的精確可控。
沿用第一個例子,我們增加相應的超時設置。由于該報表月末查詢比較頻繁,因此希望緩存有效時間長一些(7 天)。這時只需要將 A9 的表達式改為:
A9: if f.exists()&& interval(f.date(),now())<=7
判斷緩存文件如果存在,并且緩存日期為 7 天內,則讀取緩存。
本文的例子中用到的是單數據集報表,而實際上多數據集報表需要可控緩存的情況更多。一個報表的多個數據集很可能變化的頻率相差很大,有的數據集很穩定,幾天甚至幾個月都不會變,而有的數據集則可能隨時都在變化。采用部分緩存并設置不同的超時時間,這時對緩存的可用性就非常有意義了,能夠在確保報表數據正確性的同時充分利用緩存手段提高訪問性能。
需要說明的是,集算器實現可控緩存也有其適用場景,并不能完全取代常規緩存,常規緩存手段會連同報表計算結果以及呈現屬性保存在一起,而這里的可控緩存只緩存數據,在呈現時還要再次進行外觀計算,因此更適用于數據計算強度較高,但外觀計算強度較低的場景。在實際應用中,可以取長補短,將兩者結合起來使用。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。