mondrian 性能优化
mondrian作為開源的rolap引擎非常穩定,bug也非常少,但是就是基本沒用人維護了,如果出現什么問題,需要自己修改源碼了。現在很多BI工具的rolap引擎都使用的是modnrian ,例如比較出名pentaho,saiku,jpivot。這些產品只是在前端實現了一個前端展示,最終的多維度數據的聚合查詢通過mondrian完成的,但是mondrian中不支持鉆取與上卷操作,這些需要前端展示工具實現。我也開發了一個展現工具,表格鉆取自己寫的,chart用的是baidu echart,至少要比saiku好用,以后的blog單獨介紹。
由于mondrian多年沒人維護,有時遇到什么問題需要去修改mondrian的源碼,mondrian項目成立比較早,所以mondrian內部實現有些地方比較復雜,例如mondrian內部自己實現的的ioc,應該是2005年左右實現的(真的很佩服作者)。那時好像還沒有spring。但是也不是特別復雜。奉勸各位用saiku的人,想要將saiku作為產品的,還是要讀讀mondrian的源碼,bug雖然很少,但是還是有的。mondrian是無法支持24*7運行的。廢話不多說,說說主題,關于mondrian的性能優化的問題,其實mondrian性能還是不錯的,基本上百萬級別是沒有什么問題的,我用個人筆記本I3 CPU 12G的內存,數據庫(mysql)與mondrian還有查詢工具全在我一臺機器上而且都是默認設置沒有經過任何優化的前提下,我的事實表數據在16W+,沒有任何查詢效率問題。介紹mondrian優化方法前,先介紹他的工作原理,mondrian通過給定的mdx表達式生成sql,然后通過jdbc查詢數據庫中的數據,mondrian將數據加載后創建虛擬的數據矩陣。例如 用戶想分析foodmart超市,在 美國各個地區 所有各類食品銷量。
生成對應的MDX
mondrian將mdx轉換成SQL
可以看到sql中 group by 的聚合,凡是mdx中包含的Level,就會出現在sql語句中多了一個分組條件,例如,上個例子中的product_family,與product_department。mondrian會將sql查詢后的數據創建內部矩陣。關于mondrian生成的sql語句包含in的問題,有很多人問過我mondrian中的生成的SQL的語句中在條件語句中會生成帶有in ('xxxxxx','xxxxxxx') 會有in 的存在,上個例子中我是想查看product維度下,product_department層次下所有成員數據,如果我只查詢 product_department下的幾個成員的數據,這時sql語句where 后就會出現 in語句。mondrian之所以這么做的原因就是如果沒有IN操作,生成的sql語句是product_department對應分類聚合下的所有成員數據。這樣數據庫查詢一定是快于帶IN的語句,但是,這樣帶來的問題,就是不帶IN 的SQL查詢出數據集要大于帶有IN的數據集,這樣就是如果SQL的性能好了,那么mondrian對應的虛擬矩陣增大,無論在加載矩陣與數據提取時,都增大mondrian壓力。所以mondrian單獨對于判斷用戶選擇的成員的數據占總成員的數量,來定義是否采用IN SQL的形式。如果想修改這里,可以參考Aggregation.optimizePredicates(RolapStar.Column[] columns, StarColumnPredicate[] predicates)方法。mondrian的性能總體上來說兩種方法
方法一.優化數據庫
modrian只是rolap的引擎,他只只是將mdx轉換成sql,最終的查詢還是要通過數據庫來做的,所以性能的壓力大多數在DB上,所以如果出現性能問題,大家首先要測試mondrian的生成的sql,在數據庫中的執行效率,至于數據庫優化辦法估計大家就有很多辦法了,創建索引,簡化數據庫表之間的關系,沒錢的話玩玩技術,有錢的話直接上數據庫一體機什么問題都解決了。
方法二 mondrian的緩存修改
mondrian中存在緩存功能,查詢過的mdx語句會存入到緩存中。下次再次查詢是,數據將直接在緩存中讀取。但是mondrian中緩存的實現真的是一般般。
在Mondrian中使用的是軟引用,如果內存不足時,對象將會被回收。但是有些SegmentBody非常的大。這樣導致對象經常被回收。經常需要重復的查詢數據庫。所以mondrian優化可以從修改緩存的部分開始,可以將mondrian的緩存放到另一個進程里,這樣就可以大大的減輕mondriand造成的壓力。可以將緩存部分修改成現在比較流行的ehcache或memcache,而且ehcache與memcache還支持集群或者文件形式的緩存。
如果你的數據量非常的大,數據庫的查詢性能,已經無法在優化,例如非傳統數據庫 hive spark sql ,這種數據庫在查詢性能方面天生具有缺陷。這時你可以修改緩存部分來提高mondrian的易用性。在緩存中存放已經聚合完成的數據。這樣下次請求時可以直接可以在緩存中提取聚合后的數據。
分享我的優化方案,我給他命名為mondrian-cubes,mondrian-cubes實現原理就是預加載,提前通過schema計算出所有的維度組合mdx,在mondrian-cubes中緩存mdx查詢的結果。只需要將mondrian緩存模塊稍作修改將以前讀取本地緩存部分的,改成讀取mondrian-cubes中的的數據。這樣通過預加載的模式,在用戶沒有查詢之前,將聚合后的數據放到緩存中,用戶查詢直接查詢聚合后的數據。大大的增加了在大數據的情況下mondrian的可用性。尤其在非傳統數據庫hadoop hive spark sql 等帶來的問題。畢竟hadoop類數據庫并不以查詢速度為專長。
實現mondrian-cubes中遇到的問題,首先就是數據量大的問題。如果一個多維數據集(schema)有10維,每維5層,則可能產生的立方體總數是5^10≈9800000,而總的矩陣的數據單元個數更是大的驚人。所以如果你要自己實現,一定要考慮好你的數據集維度是多少,需要什么作為你的預加載cube的存儲方案。我使用的是ehcahce,我通過ehcache將數據存儲到硬盤上,我使用的mondrian foodmart.xml數據集做的測試。目前只有sales 數據集加載到200多G,因為磁盤空間不足,停止預加載,其它的數據集沒有問題。所以大家可以參考參考,還有就是預加載的數據量取決于你維度與層次多少,與實際的數據量多少沒有太大關系。預加載可能需要一段時間,可能與每個group by 語句在數據庫中的執行時間。
為了快速的加載,我采用了ehcache+terracotta集群的預加載數據,多個模塊加載可以提高加載速度,減輕存儲壓力,架構圖如下。
在說說現在比較流行的kylin,我在實現mondrian-cubes時,真的還不知道kylin這個項目,后來看過幾篇kylin的文章,但是我看了一下原理與我實現的原理相似都是創建molap,也沒有詳細用過,但是我看到有些文章說kylin并沒有完美的支持mondrian。我個人認為如果你的公司深入的使用你還是需要去深度研究研究mondrian源碼的,那么你就可以像我這樣實現這塊的功能。不是特別復雜。你可以完全根據你公司的業務隨時調整這塊的功能。例如 刷新數據,定制加載哪部分 ,加載常用相關人員。等等。
以上是個人見解 謝謝。
總結
以上是生活随笔為你收集整理的mondrian 性能优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: InfiniBand网络简介
- 下一篇: 可以轻狂、不能轻浮