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