基于開源BI平臺Openi的數據倉庫系統的設計開發
應IT168寫的專稿:http://publish.itpub.net/bi/2007-12-06/200712060945646.shtml
現在大家比較公認的商業智能系統分為報表、OLAP、數據倉庫、數據挖掘和即席查詢五大塊,本身商業智能系統也只是一個比較新的概念,也許隨著技術和應用的發展還會擴充出來很多模塊。本文就基于開源BI平臺Openi的數據倉庫系統,進行整體設計及開發,就其中比較熱門的技術,如OLP、數據倉庫等進行初步的控告,以期起到一個拋磚引玉的作用。
一、 開源的BI平臺
商業智能也稱作BI是英文單詞Business Intelligence的縮寫。商業智能通常被理解為將企業中現有的數據轉化為知識,幫助企業做出明智的業務經營決策的工具。這里所談的數據包括來自企業業務系統的訂單、庫存、交易賬目、客戶和供應商等來自企業所處行業和競爭對手的數據以及來自企業所處的其他外部環境中的各種數據。而商業智能能夠輔助的業務經營決策,既可以是操作層的,也可以是戰術層和戰略層的決策。為了將數據轉化為知識,需要利用數據倉庫、聯機分析處理(OLAP)工具和數據挖掘等技術。因此,從技術層面上講,商業智能不是什么新技術,它只是數據倉庫、OLAP和數據挖掘等技術的綜合運用。
從國內企業和政府部門的信息化建設發展來看,從最初的各類MIS系統到近幾年流行的ERP、CRM等,用戶的數據積累已達到了一定的程度,很多行業的用戶面對越來越激烈的市場競爭,他們需要對自己的數據(用戶、市場、產品)進行分析,挖掘出潛在的商機,降低公司的運作成本,這是BI和數據倉庫類產品被市場看好、不斷獲得增長的根本原因!
在現有的市場中,對于BI類產品來說往往是與數據倉庫整體解決方案相關聯,一些國內的IT公司也正在把BI和數據倉庫的結合作為行業的解決方案來推廣到自己熟悉的領域。對于IT公司來說在ERP、CRM之后需要尋找新的利潤增長點,BI和數據倉庫的出現無疑是一個莫大的商機。
在商業智能系統出現之前,大家都是通過報表來展現數據庫中的數據,報表有簡單有復雜,當然報表只能靜態的展現一部分數據,用戶只能看到已經做好的報表,不能根據自己的需要重新構造報表。隨著技術的發展,出現了OLAP分析,它能夠讓用戶根據自己的想法對數據進行聚類、分類、鉆取等操作,這樣就很好的解決了報表不能動態展現的問題。之后隨著數據倉庫和數據挖掘技術的不斷完善,大家都認為商業智能系統主要是分析數據,就把OLAP、數據倉庫和數據挖掘歸類到一起形成了BI系統,這三項確實能夠體現Intelligence的概念。因此初期的BI系統都是只含有這三塊,但是用戶在使用一段時間后認為報表模塊是必不可少的,因此都紛紛要求BI供應商將報表模塊加進來,為什么會出現這種情況呢?因為雖然OLAP能動態展現數據,但是它主要還是側重于決策者的分析,而中層領導更喜歡看到的是報表,他們需要掌握自己所分管部分的運營情況,報表則是最好的展現數據的方式,因此最后各BI廠商就將報表也加入到BI系統中去了,例如BO收購水晶報表,Hyperion收購Brio等都是BI廠商收購報表廠商來完善自己的報表功能。
下面列出相對成熟和完整,并且有借鑒意義的開源BI套件,而本文中的倉庫系統的設計及開發采用就是其中的Openi這種開源的BI平臺。
(1)、Bizgres
為GreenPlum公司主導的開源項目,和Sun公司達成合作關系。Bizgres為BI應用而對PostgreSQL做了優化,提高了大負荷的并行計算能力,在BI環境中,相對于普通的關系型數據庫具有卓越的數據處理性能。Bizgres的數據庫平臺可以和KETL和JasperReports進行整合,從而形成一個BI套件。
(2)、Openi
是一個Java開發的Web應用,能對OLAP服務器、關系數據庫和數據挖掘服務器進行分析和報表展示,非常易于使用和部署,界面美觀友好,后續還將支持數據挖掘和ETL等。
(3)、Pentaho
是一個以工作流為核心的、強調面向解決方案而非工具組件的BI套件,整合了多個開源項目,目標是和商業BI相抗衡。它包括。由上可見Pentaho是一個很完善的BI解決方案。Pentaho偏向于與業務流程相結合的BI解決方案,側重于大中型企業應用。
(4)、SpagoBI
SpagoBI 集成了Mondrain和JProvit,能夠通過OpenLaszlo產生實時報表。SpagoBI使用java開發,不依賴于具體的操作系統,有很強的擴展能力。根據其Roadmap可以看出,SpagoBI將融入更多的BI功能,甚至BI之外的功能。
二、 系統設計
1.系統體系結構
該系統基與多層體系結構設計,其中包括:
WEB客戶端層;
WEB服務器層;
數據持久層。

系統多層體系結構圖
2.系統數據流程
下面我們來介紹一下數據倉庫系統的數據流程,以此來讓用戶更好的把握產品的整體架構和功能原理。下圖為系統的數據流程與相關功能關系圖。

數據倉庫系統的數據流程
從上面的圖中我們可以看到,數據倉庫系統系統數據有兩類:業務數據和多維數據。業務數據由業務系統產生,經過一系列處理并放到數據倉庫中的關系數據庫。由于它直接來源于業務系統,因此,它真實反映了業務系統的明細數據,由于其數據量有可能很大,訪問時需要考慮要消耗的資源。
多維數據是系統從數據倉庫中經過匯總、統計而產生的。它通過采用多維結構和將一些數據預先進行了統計等預處理操作,對原始數據進行重新組合,來實現靈活而快速的數據訪問。
3.系統開發框架

系統架構圖
4.多維分析主題(CUBE)
存儲用戶所關心的某一分析主題的相關數據,其下包括多個維(分析角度)和一或多個指標。例如一個名為Sales的多維分析主題通常會包括時間、產品、門店、顧客以及指標如銷售額、成本等等。
(1)、維
維度是描述事物特征的一個角度。例如門店銷售情況需要分析商品銷售的時間、地點、商品名等。這里的時間、地點、商品名就是門店銷售情況的分析維度。
(2)、維結構
維度是有結構的,每個維度可以由若干個層次組成的,例如時間維度,可以由四個層次組成:年、季、月、日,每一個層次又由若干個維成員組成。
(3)、維成員
組成維度的子成員,如時間維度可以由其維成員2003年、2004年、2005年等具體年份來構成。
(4)、分析主題
用戶所關注業務的一個考核方面:如門點銷售情況分析,倉庫庫存情況分析等等。
(5)、指標
一個特殊的維度。它的成員都是數值型的,用來描述維度或維成員的的量屬性,例如門店銷售情況分析中的銷售額 ,商品成本等。
(6)、多維分析報表
多維分析報表中的數據來源于一個多維分析主題。多維分析主題能將同一個分析主題所涉及到的數據,即影響因素“維”和衡量因素“指標”集中存儲并且部分預先統計出來,多中角度,對從原始數據中轉化出來的、能夠真正為用戶所理解的、并真實反映企業特征的信息,進行快速、一致、交互地存取,從而獲得對數據的更深入地了解。多維分析報表的優點在于能夠擺脫業務系統數據及數據結構的限制,真正地以客戶的思維邏輯來生成報表。
三、 系統開發
1 .程序運行框架
本系統主要基于Spring Web MVC框架開發,
Action配置文件為WEB-INF"springapp-servlet.xml,
View配置文件為WEB-INF"classes"springapp-views.properties
程序運行框架圖如圖所示:

程序運行框架圖
2 .WCF組件
本系統對OLAP的操作主要基于JPivot組件實現,界面展現主要采用WCF組件進行渲染,本節對JPivot組件和WCF組件的使用進行詳細介紹。
WCF是一個JSP 自定制的標簽庫,它主要通過XSLT對XML進行渲染,創建、展現和驗證HTML表單。特別地,JPivot組件通過Renderable接口中的render方法生成組件的XML描述信息,再借助于WCF的Render標簽可以將XML描述信息轉換為HTML發布到用戶界面上。以下對WCF部分標簽的用法分別予以介紹。
(1).form
此組件采用XML文件的方式來創建HTML表單,該組件在設計階段并不中見,必須通過WCF render標記進行渲染后方可見。XML文件的格式如下:
示例:
<xform style="twocolumn">
<title value="Form Demo">
<imgButton label="Cancel" .../>
</title>
<textField type="int" modelReference="intValue" label="Count" .../>
<checkBox modelReference="nestedBean.boolValue" label="Check Me" .../>
</xform>
而它的數據綁定而言,關聯到了相關的JavaBean。通過modelReference屬性來對bean屬性注入值。當然modelReference可以包含EL表達式。
示例:
<jsp:useBean id="testbean" class="com.tonbeller.wcf.form.TestBean" scope="session" />
<wcf:form id="formcomp" xmlUri="/WEB-INF/formdemo.xml" model="#{testbean}"/>
<form action="formdemo.jsp" method="POST" id="form01">
<wcf:render ref="#{formcomp}" xslUri="/WEB-INF/wcf/wcf.xsl" xslCache="true"/>
</form>
示例:
<xform style="twocolumn">
<title value="fmt:fetch.title.from.resource.bundle">
<imgButton id="cancel" src="wcf/form/cancel.png" action="revert" label="Cancel" forward="tabledemo.jsp" handler="com.tonbeller.wcf.form.ButtonHandler"/>
</title>
<!-- Text control -->
<textField id="string" type="string" modelReference="stringValue" label="Text:" value="" title="please enter some text"/>
<textField id="int" type="int" modelReference="intValue" label="Integer:" value="" title="please enter an integer"/>
<textField id="double" type="double" modelReference="doubleValue" label="Decimal number:" value="" title="please enter a decimal number"/>
<textField id="date" type="date" modelReference="dateValue" label="Date:" value="" title="please enter a date"/>
<textField id="dateTime" type="dateTime" modelReference="dateTimeValue" label="Date/Time:" value="" title="please enter a date/time"/>
<!-- Password control -->
<password id="password" type="string" modelReference="password" label="Password:" value=""/>
<!-- Text area -->
<textArea id="textarea" rows="7" cols="40" type="string" modelReference="textArea" label="Text area:" value="This is a text area"/>
<checkBox id="checkbox1" modelReference="checkBox1" label="check box 1"/>
<checkBox id="checkbox2" modelReference="checkBox2" label="check box 2"/>
<!-- ListBox, single selection -->
<listBox1 id="list1" type="int" modelReference="list1" label="List, single selection:">
<listItem id="list1.1" value="1" label="list item 1"/>
<listItem id="list1.2" value="2" label="list item 2"/>
<listItem id="list1.3" value="3" label="list item 3"/>
<listItem id="list1.4" value="4" label="list item 4"/>
</listBox1>
<!-- ListBox, multiple selection -->
<listBoxN id="listN" type="int" modelReference="listN" label="List, multiple selection:">
<listItem id="listN.1" value="1" label="list item 1"/>
<listItem id="listN.2" value="2" label="list item 2"/>
<listItem id="listN.3" value="3" label="list item 3"/>
<listItem id="listN.4" value="4" label="list item 4"/>
</listBoxN>
<!-- ListBox, single selection, dynamic item list -->
<listBox1 id="listbox" type="int" modelReference="dynList" label="List, dynamic content:" handler="com.tonbeller.wcf.form.TestItems"/>
<label label="This is a label" value="value attribute goes here"/>
<label label="Dynamic label (content from TextArea)" modelReference="textArea"/>
<radioButton id="radio1" modelReference="radioButton1" group-id="group1" label="radio button 1"/>
<radioButton id="radio2" modelReference="radioButton2" group-id="group1" label="radio button 2"/>
<buttons>
<button id="cancel" action="revert" label="Cancel" forward="tabledemo.jsp" handler="com.tonbeller.wcf.form.ButtonHandler"/>
<button id="revert" action="revert" label="Revert" handler="com.tonbeller.wcf.form.ButtonHandler"/>
<button id="validate" action="validate" label="Validate" handler="com.tonbeller.wcf.form.ButtonHandler"/>
<button id="ok" action="validate" label="OK" forward="tabledemo.jsp" handler="com.tonbeller.wcf.form.ButtonHandler"/>
</buttons>
</xform>
3.JPivot組件
JPivot - 是一個JSP 自定制的標簽庫,可以繪制一個OLAP表格和圖表。用戶可以執行典型的OLAP操作,如上鉆、下鉆、切片、和切塊等。JPviot組件不能直接產生界面輸出,但Pviot所有的可發布的組件都實現了Renderable接口,所有組件的輸出信息都是通過Renderable接口中的render方法生成的,然后由WCF標簽庫的render標簽調用JPivot組件的render方法將組件信息輸出到界面上。以下對JPivot部分組件的用法分別予以介紹。
(1).chooseQuery
采用queryName屬性來創建查詢內容。
示例:
<jp:mondrianQuery id="query01" queryName="name1">
SELECT ...
</jp:mondrianQuery>
<jp:mondrianQuery id="query01" queryName="name2">
SELECT ...
</jp:mondrianQuery>
...
<jp:chooseQuery id="query01" queryName="name1"/>
(2).clickable
使所有的維度成員或級別可以點擊,例如產生一個鏈接。產生的URL地址包含成員的唯一名稱。當然,它的動作依賴于sessionParam屬性,當它存在時,在新頁面展示之前,參數值將寫進com.tonbeller.jpivot.param.SessionParamPool。當不存在時,參數值將通過編碼附加在超級鏈接后面。
示例:
<jp:mondrianQuery ...>
select .. from Sales
<jp:clickable urlPattern="/otherpage.jsp?param={0}" uniqueName="[Customers]"/>
<jp:clickable page="/yetotherpage.jsp" uniqueName="[Products].[Category]" sessionParam="Category"/>
</jp:mondrianQuery>
四、 系統效果
1. 設置數據源和多維模型

選擇數據源和多維模型
2. 瀏覽報表

打開并瀏覽報表