Mondrian + JPivot环境配置和演示
本文主要講解ROLAP,以及ROLAP的實現(xiàn)Mondrian的使用和部署問題。目前網(wǎng)上關(guān)于Mondrian部署的帖子較少,連官網(wǎng)也是若干年前的版本,因此,開貼記錄一下Mondrian在使用上的一些坑,關(guān)心Mondrian的使用請直接移步第二章。
1.OLAP簡介
1.1什么是OLAP
OLAP系統(tǒng),英文為OnLine Analytical Processing,中文為聯(lián)機分析處理系統(tǒng),它在數(shù)據(jù)分析和決策方面為用戶或“知識工人”提供服務(wù),以不同的格式組織和提供數(shù)據(jù),滿足不同用戶的形形色色的需求。與之相對的為OLTP(Online Transaction Processing,聯(lián)機事務(wù)處理)系統(tǒng),該系統(tǒng)主要用于單位的大部分日常操作,如購物、庫存、制造、銀行、工資、注冊、記賬等。
OLAP和OLTP的主要區(qū)別如下:
- 用戶:OLTP是面向顧客的,用于事辦員、客戶和信息技術(shù)專業(yè)人員的事務(wù)和查詢處理。OLTP是面向市場的,用于知識工人(包括經(jīng)理、主管和分析人員)的數(shù)據(jù)分析。
- 數(shù)據(jù)內(nèi)容:OLTP系統(tǒng)管理日常的、瑣碎的數(shù)據(jù),而這種數(shù)據(jù)一般很難用于決策。OLAP系統(tǒng)管理大量的歷史數(shù)據(jù),提供匯總和聚集機制,并在不同的粒度層上存儲和管理系統(tǒng)。這些特點使得數(shù)據(jù)更容易用于有根據(jù)的決策。
- 數(shù)據(jù)庫設(shè)計:通常,OLTP系統(tǒng)采用實體-聯(lián)系(ER)數(shù)據(jù)模型和面向應(yīng)用的數(shù)據(jù)庫設(shè)計。而OLAP系統(tǒng)通常采用星形或雪花模型和面向主題的數(shù)據(jù)庫設(shè)計。
- 視圖:OLTP系統(tǒng)主要關(guān)注一個企業(yè)或部門內(nèi)部的當前數(shù)據(jù),而不涉及歷史數(shù)據(jù)或不同單位的數(shù)據(jù)。相比之下,由于單位的演變,OLAP系統(tǒng)嘗嘗跨越數(shù)據(jù)庫模式的多個版本。OLAP系統(tǒng)還處理來自不同單位的信息,以及由多個數(shù)據(jù)庫集成的信息。
- 訪問模式:OLTP系統(tǒng)的訪問主要由短的原子事務(wù)組成。這種系統(tǒng)需要并發(fā)控制和恢復(fù)機制。然而,對OLAP系統(tǒng)的訪問大部分是只讀操作,大多數(shù)是復(fù)雜的查詢。
OLTP和OLAP的主要區(qū)別之一在于數(shù)據(jù)庫的選擇,由于OLTP系統(tǒng)是面向顧客的、需要并發(fā)控制和恢復(fù)機制,因此OLTP系統(tǒng)往往采用關(guān)系數(shù)據(jù)庫,如MySQL、Oracle數(shù)據(jù)庫等。而OLAP系統(tǒng)一般是只讀的、大量歷史數(shù)據(jù)的匯總和聚集,因此OLAP往往使用數(shù)據(jù)倉庫。
寬泛地講,數(shù)據(jù)倉庫是一種數(shù)據(jù)庫,它與單位的操作數(shù)據(jù)庫分別維護。數(shù)據(jù)倉庫系統(tǒng)允許將各種應(yīng)用系統(tǒng)集成在一起,為統(tǒng)一的歷史數(shù)據(jù)分析提供堅實的平臺,對信息處理提供支持。面向主題的、集成的、時變的、非易失的是數(shù)據(jù)倉庫的主要特征,也是將數(shù)據(jù)倉庫與其他數(shù)據(jù)存儲系統(tǒng)(如關(guān)系數(shù)據(jù)庫系統(tǒng)、事務(wù)處理系統(tǒng)和文件系統(tǒng))相區(qū)別。
- 面向主題的(subject-oriented):數(shù)據(jù)倉庫圍繞一些重要主題,如顧客、供應(yīng)商、產(chǎn)品和銷售組織,關(guān)注決策者的數(shù)據(jù)建模與分析,拍除對于決策無用的數(shù)據(jù),提供特地主題的簡明視圖。
- 集成的(integrated):構(gòu)造數(shù)據(jù)倉庫通常是將多個異構(gòu)數(shù)據(jù)源,如關(guān)系數(shù)據(jù)庫、一般文件和聯(lián)機事務(wù)處理記錄集成在一起。
- 時變的(time-variant):數(shù)據(jù)存儲從歷史的角度提供信息。數(shù)據(jù)倉庫中的關(guān)鍵結(jié)構(gòu)都隱式或顯示地包含時間元素。
- 非易失的(nonvolatile):數(shù)據(jù)倉庫不需要事務(wù)處理、恢復(fù)和并發(fā)控制機制。通常,它只需要兩種數(shù)據(jù)訪問操作:數(shù)據(jù)的初始化裝入和數(shù)據(jù)訪問。
通常,數(shù)據(jù)倉庫采用三層體系結(jié)構(gòu):
1.2?為什么需要使用分離的數(shù)據(jù)倉庫
分離的主要原因是有助于提高兩個系統(tǒng)的性能。操作數(shù)據(jù)庫是為已知的任務(wù)和負載設(shè)計的。另一方面,數(shù)據(jù)倉庫的查詢通常是復(fù)雜的,涉及大量數(shù)據(jù)在匯總級的計算,可能需要特殊的基于多維視圖的數(shù)據(jù)組織、存取方法和實現(xiàn)方法。在操作數(shù)據(jù)庫上處理OLAP查詢,可能會大大降低操作任務(wù)的性能。此外,操作數(shù)據(jù)庫支持多事務(wù)的并發(fā)處理,需要并發(fā)控制和恢復(fù)機制,以確保一致性和事務(wù)的魯棒性。通常,OLAP查詢只需要對匯總和聚集數(shù)據(jù)記錄進行只讀訪問。最后,數(shù)據(jù)倉庫與操作數(shù)據(jù)庫分離是由于這兩種系統(tǒng)中數(shù)據(jù)的結(jié)構(gòu)、內(nèi)容和用法都不相同。
1.3?OLAP服務(wù)器的結(jié)構(gòu):ROLAP、MOLAP和HOLAP
用于OLAP處理的數(shù)據(jù)倉庫服務(wù)器的實現(xiàn)包括了ROLAP(關(guān)系OLAP)、MOLAP(多維OLAP)和HOLAP(混合OLAP),ROLAP服務(wù)器是一種中間服務(wù)器,介于關(guān)系的后端服務(wù)器和客戶前端工具之間,它們使用關(guān)系的或擴充關(guān)系的DBMS存儲并管理數(shù)據(jù)倉庫數(shù)據(jù),而OLAP中間件支持其余部分,相應(yīng)的實現(xiàn)有Mondrian等;MOLAP服務(wù)器通過基于數(shù)組的多維存儲引擎,支持數(shù)據(jù)的多維視圖,它們將多維視圖直接映射到數(shù)據(jù)立方體數(shù)組結(jié)構(gòu)。使用數(shù)據(jù)立方體的優(yōu)點是能夠?qū)︻A(yù)計算的匯總數(shù)據(jù)快速索引,相應(yīng)的實現(xiàn)有Cognos,SSAS,Kylin等;HOLAP服務(wù)器結(jié)合ROLAP和MOLAP技術(shù),得益于ROLAP較大的可伸縮性和MOLAP的快速計算,比如微軟的SQL Server2000。它們的區(qū)別的表格如下:
| 名稱 | 描述 | 細節(jié)數(shù)據(jù)存儲位置 | 聚合后的數(shù)據(jù)存儲位置 | 代表 |
| ROLAP | 基于關(guān)系數(shù)據(jù)庫的OLAP實現(xiàn) | 關(guān)系型數(shù)據(jù)庫 | 關(guān)系型數(shù)據(jù)庫 | Mondrian |
| MOLAP | 基于多維數(shù)據(jù)組織的OLAP實現(xiàn) | 數(shù)據(jù)立方體 | 數(shù)據(jù)立方體 | Cognos,SSAS,Kylin |
| HOLAP | 基于混合數(shù)據(jù)組織的OLAP實現(xiàn) | 關(guān)系數(shù)據(jù)庫 | 數(shù)據(jù)立方體 | SQL Server |
個人認為上面的幾種方式?jīng)]有絕對的優(yōu)劣之分,選擇哪種結(jié)構(gòu)還是和具體的應(yīng)用有關(guān)。?
2.Mondrian+JPivot
Mondrian是ROLAP的實現(xiàn)之一,它是搭配構(gòu)建數(shù)據(jù)立方體的XML文件,根據(jù)訪問的MDX語句動態(tài)查詢數(shù)據(jù)庫,在內(nèi)存中存儲數(shù)據(jù)立方體,并返回結(jié)果,因此,Mondrian對內(nèi)存的要求較高。
官網(wǎng)地址:https://mondrian.pentaho.com/documentation/olap.php。通過查看官網(wǎng),你會發(fā)現(xiàn),Mondrian是提供了war包的,然而,官網(wǎng)有關(guān)于[安裝]的內(nèi)容應(yīng)該滯后若干個版本,也就是說,單純的Mondrian只是提供了jar包,如果想要使用線上展示結(jié)果的功能,需要搭配JPivot一起使用,JPivot提供war包,它需要Mondrian的jar包,然后配合jsp代碼來實現(xiàn)網(wǎng)頁的可視化。有關(guān)于Mondrian和JPivot的環(huán)境配置,請參考參考文章的第三個Mondrian + JPivot 環(huán)境配置。從https://pan.baidu.com/s/1zkSyZJkTGabEFwcfsktDCw?下載?mondrian server.rar ,?test-mondrian.rar。本小節(jié)主要講解JPivot的粗略的運行方式。
test-mondrian.rar為控制臺運行的方式,運行Main.java,輸出如下:
Axis #0: {} Axis #1: {[Measures].[Amount]} Axis #2: {[AccessTime].[AllTime], [WebsiteNum].[AllSite], [UserIP].[AllIP]} Row #0: 278?Main.java中的MDX語句是查詢所有訪問記錄的總次數(shù),查詢結(jié)果為278。但是控制臺查詢的弊端在于不夠直觀,比如MDX語句為:
SELECT {[Measures].[Unit Sales], [Measures].[Store Sales], [Measures].[Profit]} ON COLUMNS, {descendants([Time].[1997].[Q1])} ON ROWS FROM [Sales] WHERE [Gender].[F]?旨在查詢1997年第一季度的所有月份,女性的消費記錄,輸出如下:
Axis #0: {[Gender].[All Genders].[F]} Axis #1: {[Measures].[Unit Sales]} {[Measures].[Store Sales]} {[Measures].[Profit]} Axis #2: {[Time].[1997].[Q1]} {[Time].[1997].[Q1].[February]} ... {[Time].[1997].[Q1].[March].[15].[Sunday]} Row #0: 32,910 Row #0: 69,798.23 Row #0: $41,976.46 Row #1: 10,266 Row #1: 21,773.93 Row #1: $13,110.09 Row #2: 207 Row #2: 414.6 Row #2: $246.12 Row #3: 207 Row #3: 414.6 Row #3: $246.12 Row #4: 2,871 Row #4: 5,940.83 Row #4: $3,580.08 ... Row #109: 206 Row #109: 405.37 Row #109: $239.28?那么控制臺方式的輸出方式的缺點則更加凸顯,接下來,則開始講解JPivot。
參考文章3已經(jīng)給出了一個簡單的demo,該示例為上述輸出的jsp版本。接下來主要分析,在jpivot.war的基礎(chǔ)上,如何自行添加相關(guān)的jsp頁面。這里假設(shè)tomcat已經(jīng)處于運行之中,那么輸入http://127.0.0.1:8080/jpivot/index.jsp,頁面如下:
在上述頁面中,AccessInfo為壓縮包中的Sample Demo,FoodMart3為第二個MDX語句的輸出結(jié)果,首先觀察index.jsp,該文件在webapps\jpivot文件夾下,打開:
... <ul><li><a href="testpage.jsp?query=mondrian">Slice and Dice with two hierarchies</a></li><li><a href="testpage.jsp?query=fourhier">...and with four hierachies</a></li><li><a href="test/param3.jsp?query=mondrian">Dynamic parameters with Mondrian</a></li><li><a href="testpage.jsp?query=arrows">Arrows in Cells</a></li><li><a href="testpage.jsp?query=colors">Colors in Cells</a></li><li><a href="testpage.jsp?query=testquery">Test data</a></li><li><a href="testpage.jsp?query=AccessInfo">AccessInfo</a></li><li><a href="testpage.jsp?query=FoodMart3">FoodMart3</a></li><li><a href="test/param1.jsp?query=testquery">Dynamic parameters with test data</a></li> </ul> ...?通過對比網(wǎng)頁發(fā)現(xiàn),<li><a href="testpage.jsp?query=AccessInfo">AccessInfo</a></li>為入口URL,那么接著打開testpage.jsp,第44行:
<%-- include query and title, so this jsp may be used with different queries --%> <wcf:include id="include01" httpParam="query" prefix="/WEB-INF/queries/" suffix=".jsp"/>prefix為前綴,suffix為后綴,再結(jié)合傳入的query,整合起來就是?/WEB-INF/queries/AccessInfo.jsp,接著打開該文件:
<%@ page import="mondrian.olap.*"%> <%@ page session="true" contentType="text/html; charset=UTF-8" %> <%@ taglib uri="http://www.tonbeller.com/jpivot" prefix="jp" %> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %><jp:mondrianQuery id="query01" jdbcDriver="com.mysql.jdbc.Driver" jdbcUrl="jdbc:mysql://localhost/jpivot" catalogUri="/WEB-INF/queries/AccessInfo.xml" jdbcUser="jpivot" jdbcPassword="jpivot" connectionPooling="false">select NON EMPTY {[Measures].[Amount]} ON COLUMNS,NON EMPTY{([AccessTime].[AllTime], [WebsiteNum].[AllSite], [UserIP].[AllIP]) } ON ROWSfrom [AccessAnalysis] </jp:mondrianQuery>?可以發(fā)現(xiàn),該文件就是Main.java文件的jsp實現(xiàn)方式,可視化展示查詢結(jié)果:
JPivot還提供了諸如下鉆、上卷,圖表等功能,比如此時點擊AllTime可以觀察不同時間(注:我個人的數(shù)據(jù)庫中的部分數(shù)據(jù)存在修改,與db.sql不同):
此時可以把AllTime關(guān)閉,點擊AllIP可以擦好看不同IP的訪問次數(shù):
再點擊AllSite,可以查看哪些IP訪問了哪些網(wǎng)站:
點擊顯示圖表,默認展示柱狀圖:
總結(jié):Mondrian+JPivort是比較強大的ROLAP工具,尤其是JPivot可以以可視化的形式展示結(jié)果。本示例只是展示了Mondrian的冰山一角。后續(xù)我可能會發(fā)布一些細節(jié)的功能實現(xiàn),比如以restful的形式提供功能等。
3.注意事項
3.1 JPivot MDX編輯框中文亂碼和數(shù)據(jù)查詢問題
在Mondrian中有兩個有關(guān)于使用中文會遇到的坑,第一個就是在JPivot的MDX編輯界面時,輸入的中文會亂碼。這個問題我參考網(wǎng)上的并沒有解決。。。
第二個則是我個人遇到的坑。目前互聯(lián)網(wǎng)上有關(guān)Mondrian的連接一般是下面的流程:
package com.mondrian;import java.io.PrintWriter;import mondrian.olap.Connection; import mondrian.olap.DriverManager; import mondrian.olap.Query; import mondrian.olap.Result;public class Main {public static void main(String[] args) {String connectString = "Provider=mondrian;Jdbc=jdbc:mysql://127.0.0.1/FoodMart?user=root&password=root;Catalog=FoodMart3.xml;";Connection connection = DriverManager.getConnection(connectString,null);String mdx = "SELECT {[Measures].[Unit Sales], [Measures].[Store Sales], [Measures].[Profit]} ON COLUMNS," +" {[Time].[1997].[Q1]} ON ROWS" +" FROM [Sales] WHERE [Gender].[Gender].[男]";Query query = connection.parseQuery(mdx);Result result = connection.execute(query);PrintWriter pw = new PrintWriter(System.out);result.print(pw);pw.flush(); } }FoodMart3.xml是官方提供的一個示例,其文件內(nèi)容如下:
<?xml version="1.0"?> <Schema name="FoodMart2"><Cube name="Sales"><Table name="sales_fact_1997"/><!--維表 性別--><Dimension name="Gender" foreignKey="customer_id"><Hierarchy hasAll="true" allMemberName="All Genders" primaryKey="customer_id"><Table name="customer"/><Level name="Gender" column="gender_zh" uniqueMembers="true"/></Hierarchy></Dimension><!--維表 時間--><Dimension name="Time" foreignKey="time_id"><Hierarchy hasAll="false" primaryKey="time_id"><Table name="time_by_day"/><Level name="Year" column="the_year" uniqueMembers="true"/><Level name="Quarter" column="quarter" uniqueMembers="false"/><Level name="Month" column="the_month" type="String" uniqueMembers="false"/><Level name="Week" column="week_of_year" uniqueMembers="false"/><Level name="Day" column="the_day" type="String" uniqueMembers="false"/></Hierarchy></Dimension><!--度量--><Measure name="Unit Sales" column="unit_sales" aggregator="sum" formatString="#,###"/><Measure name="Store Sales" column="store_sales" aggregator="sum" formatString="#,###.##"/><Measure name="Store Cost" column="store_cost" aggregator="sum" formatString="#,###,00"/><!--新定義的一個度量 Profit=[Store Sales] - [Store Cost]--><CalculatedMember name="Profit" dimension="Measures" formula="[Measures].[Store Sales] - [Measures].[Store Cost]"><CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/></CalculatedMember></Cube> </Schema>注:在FoodMart3.xml文件中,我所做的就是在FoodMart數(shù)據(jù)庫中的customer表添加了一個gender_zh字段,其值可能是男或女。
首先是連接mysql數(shù)據(jù)庫和數(shù)據(jù)立方體的配置文件,然后一個查詢的MDX語句,最后則是輸出。使用這種方法貌似沒有問題,但是,此時輸出會返回空:
Axis #0: {[Gender].[All Genders].[男]} Axis #1: {[Measures].[Unit Sales]} {[Measures].[Store Sales]} {[Measures].[Profit]} Axis #2: {[Time].[1997].[Q1]} Row #0: Row #0: Row #0:?其中的一個主要原因,也就是我遇到的原因,就是在使用jdbc連接mysql數(shù)據(jù)庫的時候,沒有指定編碼方式,因此connectString應(yīng)該改為:
String connectString = "Provider=mondrian;Jdbc=jdbc:mysql://127.0.0.1/FoodMart?useUnicode=true&characterEncoding=utf-8&user=root&password=root;Catalog=FoodMart3.xml;";此時輸出正常:
Axis #0: {[Gender].[All Genders].[男]} Axis #1: {[Measures].[Unit Sales]} {[Measures].[Store Sales]} {[Measures].[Profit]} Axis #2: {[Time].[1997].[Q1]} Row #0: 33,381 Row #0: 69,830.12 Row #0: $41,899.65如果是在JPivot中使用的話,則需要在jsp文件的<jp:mondrianQuery>的jdbcUrl添加userEncoding和characterEncoding即可:
<jp:mondrianQuery id="query01" jdbcDriver="com.mysql.jdbc.Driver" jdbcUrl="jdbc:mysql://127.0.0.1/ren_db?useEncoding=true&characterEncoding=utf-8" catalogUri="/WEB-INF/queries/FoodMart3.xml" jdbcUser="root" jdbcPassword="root" connectionPooling="false">SELECT {[Measures].[Unit Sales], [Measures].[Store Sales], [Measures].[Profit]} ON COLUMNS,{[Time].[1997].[Q1]} ON ROWS FROM [Sales] WHERE [Gender].[Gender].[男] </jp:mondrianQuery>3.2 Mondrian的版本問題
?目前官方同時維護的Mondrian版本有3.x、4.x和8.x。在github地址也并沒有過多提及相關(guān)的區(qū)別,在mondrian-rest(Mondrian-rest使用spring boot實現(xiàn)了Mondrian的restful API)中關(guān)于Mondrian版本的部分介紹為:
Initial development of mondrian-rest supported version 4.x of the Mondrian library. However, Mondrian 4.x does not appear to be under active development by the core Mondrian maintainers, so we have abandoned it as a dependency. The last version of mondrian-rest that supports version 4.x schemas is version 1.5.0. PRs for the 1.x line of mondrian-rest will be considered, but active development of mondrian-rest by the core committers is focused on Mondrian 8.x (and, at some point, version 9.x). There are significant schema differences between 4.x and 8.x+, however for the most part, the mondrian-rest API is consistent between mondrian-rest v2.x and v1.x.
內(nèi)容大致是:
Mondrian-rest的初始開發(fā)支持Mondrian的4.x版本。但是,mondrian4.x似乎并沒有被核心維護人員積極開發(fā),所以我們放棄了它作為一個依賴項。支持版本4.x架構(gòu)的mondrian-rest的最后一個版本是版本1.5.0。mondrian-rest的積極開發(fā)主要集中在Mondrian的8.x版本(在某些情況下,版本9.x)。4.x和8.x+之間存在顯著的模式差異,但是在大多數(shù)情況下,mondrian-rest api在mondrian-rest v2.x和v1.x之間是一致的。?
3.3 可視化
Mondrian官方推薦使用JPivot實現(xiàn)OLAP的可視化,雖然JPivot在交互上較為強大,但是我個人認為它在可視化和使用上要略差,而且JPivot官網(wǎng)的war包很久沒有更新了,因此,這里我個人推薦使用Saiku來實現(xiàn)Mondrian的可視化。有關(guān)于Saiku的快速上手,我推薦這個資源:saiku2.6解壓我的Tomcat資源可以直接運行,以及這個帖子:saiku2.6完整版(運行Tomcat可以直接使用)。俗話說,百聞不如一見,通過這個資源和配套的這個帖子可以快速上手Saiku,在大致了解了saiku的功能后可以考慮是否使用saiku。
4.參考文章
淺談ROLAP、MOLAP和HOLAP區(qū)別
OLTP與OLAP的關(guān)系是什么?
Mondrian + JPivot 環(huán)境配置
《數(shù)據(jù)挖掘 概念與技術(shù)》
MDX語句(初學者)
Mondrian使用教程
mysql 中文java_java鏈接mysql 中文亂碼
總結(jié)
以上是生活随笔為你收集整理的Mondrian + JPivot环境配置和演示的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国科大英语Unit5
- 下一篇: ELK+kafka集群实战