mondrian源碼分析與說明.doc_第1頁
mondrian源碼分析與說明.doc_第2頁
mondrian源碼分析與說明.doc_第3頁
mondrian源碼分析與說明.doc_第4頁
mondrian源碼分析與說明.doc_第5頁
已閱讀5頁,還剩20頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

mondrian源碼分析1.概述11.1.若干概念11.2.架構(gòu)22.靜態(tài)類包分析32.1.包解釋32.2.Schema manger部分42.3.包mondrian.calc42.4.包mondrian.olap接口52.4.1.mdx函數(shù)包52.4.2.funCall52.4.3.Query類62.5.包mondrian.rolap計(jì)算層62.5.1.成員讀取包MemberReader62.5.2.單元格讀取CellReader82.5.3.RolapResult類112.5.4.RolapEvaluator類122.5.5.關(guān)于排序122.6.聚集層Star layer132.6.1.概述132.6.2.聚合裝載過程132.6.3.segment詳解142.6.4.緩存失效控制173.交互管理層183.1.初始化MondrianModel183.2.獲取結(jié)果集194.修改點(diǎn)224.1.mondrian角色參數(shù)化224.2.緩存失效控制224.3.connection創(chuàng)建參數(shù)優(yōu)化234.4.維度成員排序234.5.對(duì)mondrian bug的修正244.6.to-do List241. 概述1.1. 若干概念成員(member):成員是代表維度中一次或多次數(shù)據(jù)出現(xiàn)的項(xiàng)。度量值也可以算作一個(gè)維度,因此一個(gè)具體度量值項(xiàng)也可以作為一個(gè)成員。元組(tuple):是向量,用于定義來自多維數(shù)據(jù)集的數(shù)據(jù)切片;它由來自一個(gè)或多個(gè)維度的單個(gè)成員的有序集合組成。元組用于標(biāo)識(shí)來自多維數(shù)據(jù)集的特定多維數(shù)據(jù)塊;由來自多維數(shù)據(jù)集中各個(gè)維度的一個(gè)成員組成的元組完全描述單元值。換言之,元組是一種成員向量。例如:(時(shí)間.下半年, 路線.非陸地.航空),由單個(gè)成員組成的元組也可括在圓括號(hào)內(nèi),但這不是必需的。單元(cell):多維成員的交集創(chuàng)建單元,可以是單個(gè)單元或單元塊。元組唯一標(biāo)識(shí)多維數(shù)據(jù)集中的一部分;它不必指某個(gè)特定單元,也不必包括多維數(shù)據(jù)集中的所有維度。集合(set):集合是零個(gè)、一個(gè)或多個(gè)元組的有序集合。集合最常用于在 MDX 查詢中定義軸維度和切片器維度,并且同樣可能只具有單個(gè)元組或可能在某些情況下為空。下面的示例顯示具有兩個(gè)元組的集合: (時(shí)間.上半年, 路線.非陸地.航空), (時(shí)間.下半年, 路線.非陸地.海路) 1.2. 架構(gòu)mondrian總共包含四個(gè)層次:表示層,計(jì)算層,聚集層,存儲(chǔ)層.。表示層(presentation layer):指最終呈現(xiàn)在用戶顯示器上的,以及與用戶之間的交互,有許多方法來展現(xiàn)多維數(shù)據(jù),包括數(shù)據(jù)透視表,餅,柱,線狀圖. 計(jì)算層(dimensional layer):分析,驗(yàn)證,執(zhí)行MDX查詢. 一個(gè)mdx查詢語句會(huì)有多個(gè)處理階段。先是計(jì)算軸,然后是軸上的單元值。為效率起見,計(jì)算層批量將單元請(qǐng)求發(fā)送到聚集層。請(qǐng)求轉(zhuǎn)換器允許程序操作存在的請(qǐng)求,而不是為每個(gè)請(qǐng)求從頭構(gòu)造mdx請(qǐng)求。元數(shù)據(jù)描述了計(jì)算模型和它怎么匹配到關(guān)系模型。聚集層(star layer):一個(gè)聚集指內(nèi)存中一組計(jì)算值(cell),這些值通過維列來限制.計(jì)算層發(fā)送單元請(qǐng)求,如果請(qǐng)求不在緩存中,或者不能通過旋轉(zhuǎn)聚集導(dǎo)出的話,聚集層向存儲(chǔ)層發(fā)送請(qǐng)求. 聚集層是一個(gè)數(shù)據(jù)緩沖層(cache),從數(shù)據(jù)庫來的單元數(shù)據(jù),聚合后提供給計(jì)算層。聚集層的主要作用是提高系統(tǒng)的性能。 存儲(chǔ)層:提供聚集單元數(shù)據(jù)(cell)和維表的成員(member),這些層可以不在同一機(jī)子上,但是計(jì)算和聚集層必須在同一臺(tái)機(jī)子上。有三種需要存儲(chǔ)的數(shù)據(jù):事實(shí)數(shù)據(jù)(事實(shí)表)、維度表和聚集數(shù)據(jù)(即聚合表)架構(gòu)圖如下:2. 靜態(tài)類包分析2.1. 包解釋mondrian.calc 提供編譯好的表達(dá)式。mondrian.gui 設(shè)計(jì)Mondrian schema的圖形接口mondrian.i18n 國際化和本地化工具mondrian.mdx 為mdx表達(dá)式定義解析樹mondrian.olap 核心包,定義了連接和schema的元模型,用來執(zhí)行查詢mondrian.olap4j 中間層,olap服務(wù)器的驅(qū)動(dòng),用來代替jolap的mondrian.recorder 任務(wù)處理記錄接口mondrian.rolap olap包的數(shù)據(jù)訪問層的實(shí)現(xiàn)mondrian.spi 用戶自定義擴(kuò)展的服務(wù)端支持接口mondrian.tui Mondrian文本用戶接口mondrian.udf 用戶定義方法mondrian.util Mondrian工具包mondrian.web Mondrian的servlet和tag庫mondrian.xmla xml for analysis API的實(shí)現(xiàn)2.2. Schema manger部分Mondrian.rolap.RolapSchema類是mondrian schema的核心類,該類在在建立RolapConnection時(shí)被建立,但是有個(gè)schema Pool維護(hù)著schema的緩存,參見RolapSchema.Pool內(nèi)部類。在RolapSchema對(duì)象生成之前,首先有個(gè)原始的MondrianDef$Schema對(duì)象,該對(duì)象相當(dāng)于mondrian schema xml文件的簡單對(duì)應(yīng),由xml解析器直接生成。具體來說首先由xml文件解析成dom對(duì)象,然后再生成更加結(jié)構(gòu)化的MondrianDef$Schema,最后再load成更加高級(jí)的RolapSchema對(duì)象,具體參見RolapSchema.load(String catalogUrl,String catalogStr);以MondrianDef$Schema或RolapSchema對(duì)象為根,都還會(huì)有一系列的內(nèi)部類去對(duì)應(yīng)于mondrian schema下的子元素。如果一個(gè)Hierarchy的hasAll為true,則會(huì)有一個(gè)all member,對(duì)應(yīng)著也需要一個(gè)虛擬的all level,位于該Hierarchy的levels0位置。2.3. 包mondrian.calcCalc是所有可計(jì)算表達(dá)式的基接口。在mondrian中關(guān)于表達(dá)式有如下兩個(gè)概念: n The logical language of parsed MDX fragments (Exp). n The phyiscal language of compiled expressions (Calc). 兩種語言可以允許我們將邏輯語言(即mdx語言) 和物理語言(how it is to be evaluated) 分開. 物理語言對(duì)類型的要求更加嚴(yán)格, and certain constructs which are implicit in the logical language (such as the addition of calls to the .CurrentMember function) are made explicit in the physical language。Calc接口針對(duì)各種類型有許多子接口:其中IntegerCalc, BooleanCalc, DoubleCalc, StringCalc是數(shù)值型的,MemberCalc, LevelCalc, HierarchyCalc, DimensionCalc則用于olap模型中的元素。每一個(gè)子接口有都有一個(gè)實(shí)現(xiàn)的虛基類:AbstractIntegerCalc, AbstractBooleanCalc, AbstractDoubleCalc, AbstractStringCalc, AbstractMemberCalc, AbstractLevelCalc, AbstractHierarchyCalc, AbstractDimensionCalc。表達(dá)式(Expression)通常由表達(dá)式編譯者(ExpCompiler)創(chuàng)建。對(duì)于一個(gè)給定的表達(dá)式通常有若干個(gè)evaluation策略,表達(dá)式編譯者在編譯過程中可以給我們一個(gè)選擇的機(jī)會(huì)。2.4. 包mondrian.olap接口Mondrian的核心包,定義了連接對(duì)象和完整的olap模型結(jié)構(gòu)元對(duì)象,并且允許執(zhí)行mdx查詢語句。2.4.1. mdx函數(shù)包mondrian.olap.fun 定義了mdx內(nèi)置的函數(shù)集。函數(shù)(function)的定義:參數(shù)描述例子name函數(shù)名Memberssignature函數(shù)標(biāo)志.Membersdescription函數(shù)描述Returns the set of all members in a dimension.flagsEncoding of the syntactic type, return type, and parameter types of this operator. The encoding is described below.pxdThe flags field is an string which encodes the syntactic type, return type, and parameter types of this operator. The first character determines the syntactic type, as described by FunUtil.decodeSyntacticType(String). The second character determines the return type, as described by FunUtil.decodeReturnCategory(String). The third and subsequence characters determine the types of the arguments arguments, as described by FunUtil.decodeParameterCategories(String). For example, pxd means an operator with property syntax (p) which returns a set (x) and takes a dimension (d) as its argument.2.4.2. funCallA FunCall is a function applied to a list of operands. The parser creates function calls as an unresolved function call. The validator converts it to a resolved function call, which has a function definition and extra type information。參見:Mondrian.olap. ResolveFunCall UnresolveFunCall 2.4.3. Query類用于mdx 查詢。. 創(chuàng)建query創(chuàng)建:Connection.parseQuery(java.lang.String)。 創(chuàng)建mondrian.olap.Parser類,基于java_cup實(shí)現(xiàn),調(diào)用其parse或debug_parse()方法,里面最主要 是CUP$Parser$do_action()方法,內(nèi)部針對(duì)所有語句詞句做了解析。其中case75:生成最后的mondrian.olap.Query對(duì)象,內(nèi)部調(diào)用parser.makeQuery()方法,內(nèi)部初始化時(shí)會(huì)再調(diào)用query的resolve,mondrian.olap.QueryAxis的resolve(),進(jìn)而會(huì)執(zhí)行數(shù)據(jù)庫。. 執(zhí)行query執(zhí)行:Connection.execute(mondrian.olap.Query)返回結(jié)果: Result.有些查詢從緩存中讀取,非常迅速。當(dāng)也有些需要花費(fèi)些時(shí)間,這時(shí)可以通過MondrianProperties.QueryTimeout參數(shù)設(shè)置timeout。如果想控制返回結(jié)果不至于太大,可以通過MondrianProperties.QueryLimit參數(shù)控制返回的cell數(shù)目。在查詢執(zhí)行的任何時(shí)候,另一個(gè)進(jìn)程都可以通過cancel()方法取消該查詢,此時(shí)Connection.execute(Query)會(huì)拋出異常。2.5. 包mondrian.rolap計(jì)算層實(shí)現(xiàn)最終的實(shí)際的olap數(shù)據(jù)訪問功能,包括讀取維度成員值和cell值。2.5.1. 成員讀取包MemberReader. 概述包路徑:Mondrian.rolap。該部分的起點(diǎn)是RolapEvaluator類。當(dāng)一個(gè)類似于“member.children”的成員表達(dá)式被請(qǐng)求時(shí), RolapEvaluator將調(diào)用RolapSchemaReader對(duì)象. RolapSchemaReader將再負(fù)責(zé)調(diào)用各個(gè)MemberReader對(duì)象(每個(gè)維度一個(gè)memberReader)。在大部分場合下,將使用SmartMemberReader 來迅速返回所需要的維度成員值。. SmartMemberReaderSmartMemberReader實(shí)現(xiàn)了MemberReader接口,它實(shí)現(xiàn)了維度成員及其子成員的緩存,如果有一個(gè)成員位于緩存中,則還會(huì)有一個(gè)其子成員的列表。它同時(shí)緩存了level下的成員們。該類主要的成員有:source:MemberReader,用于實(shí)際從數(shù)據(jù)庫中讀取維度成員值。mapMemberToChildren:map,實(shí)現(xiàn)成員及其子成員的映射,key為RolapMember,value為List。mapKeyToMember: map ,實(shí)現(xiàn)所有成員的緩存,其中的key為MemberKeymapLevelToMembers: map,實(shí)現(xiàn)級(jí)別及其所有成員的映射,key為RolapLevel,value為List。上述的source其實(shí)為mondrian.rolap.SqlMemberSource類,該類中反過來又存儲(chǔ)了SmartMemberReader對(duì)象,作為其cache成員屬性。成員讀取過程:n smartMemberReader.getMemberChildren(parentMembers,children,constrain);n 最終通過source.getMemberChildren(),其中反過來會(huì)把找到的children賦予mapKeyToMember。n 最終除了將結(jié)果返回在children輸出參數(shù)中,同時(shí)也對(duì)mapMemberToChildren賦值了。另外,smartMemberReader.getMembersInlevel()實(shí)現(xiàn)了對(duì)mapLevelToMembers的緩存。在new RolapEvaluator()時(shí)被調(diào)用。在讀取時(shí)會(huì)對(duì)成員進(jìn)行order by(如果設(shè)置了ascending的話。)2.5.2. 單元格讀取CellReader. 概述包路徑:Mondrian.rolap。Cells會(huì)被求值多次。第一次時(shí), Evaluator使用FastBatchingCellReader來求值。當(dāng)一個(gè)單元被求值時(shí),evaluateCurrent()被調(diào)用。此時(shí)FastBatchingCellReader并沒有被調(diào)用,而是為那個(gè)cell記錄了一個(gè) CellRequest并且return (not throw) an exception。在所有的cells都有了對(duì)應(yīng)的CellRequests之后, Aggregation會(huì)生成 SQL,以一個(gè)單獨(dú)的sql請(qǐng)求來載入所有的cells。然后由AggregatingCellReader 重新計(jì)算cells,從緩存中返回cells值。. FastBatchingCellReader類主要方法,Object get(Evaluator evaluator)n 首先根據(jù)當(dāng)前的上下文環(huán)境(即一組members)創(chuàng)建cellRequest,cellRequest中包含了所有必要的從star中取值的信息。該組members的交集便是要求值的單元格,其中切片軸上的成員和其他軸上的成員完全同等對(duì)待;其中度量軸上的成員要求上StoredMeasure(非計(jì)算成員CaculatedMember);度量值上的成員位于第一個(gè)。通過調(diào)用request的addConstrainedColumn()方法把各member對(duì)應(yīng)的column和value(屬StarColumnPredicate)值加至到request中.n 調(diào)用AggregationManager.getCellFromCache(request,pinnedSegments)方法從緩存中獲取cell值。首先根據(jù)request中的列組索引標(biāo)識(shí)從緩存中獲取aggreation緩存對(duì)象,如果為空說明緩存還未建立則直接返回null,如果有值則調(diào)用aggregation.getCellValue(measure,colValueKeys)方法獲取緩存的cell值;getCellValue內(nèi)部首先會(huì)根據(jù)measure查找匹配的segment,然后調(diào)用segment.getCellValue(keys)從segment的dataset緩存集中查找相應(yīng)的cell值。n 如果getCellFromCache返回為null則調(diào)用recordCellRequest()記錄需求。這些cell request會(huì)被組織成多個(gè)cell request batch,以便將來聚合層進(jìn)行批讀取以提高效率。關(guān)于batch的詳細(xì)討論參見下面Batch類章節(jié)。n 上層會(huì)在適當(dāng)?shù)臅r(shí)候調(diào)用batchCellReading.loadAggregations()以實(shí)際讀取這些cell值,前提是batches對(duì)象中已有cellRequest了。每個(gè)batch的讀取參見batch. loadAggregation()方法,最終調(diào)用聚合層的方法,參見aggreation.load(.)。. FastBatchingCellReader.Batch類每個(gè)batch對(duì)應(yīng)與一組特定的columns環(huán)境下的cell求?。ň哂邢嗤牧泻土兄?列值是具體的值,不會(huì)是“all”值));從batch的屬性可以看出batch包含了哪些上下文:n RolapStar.Column,這個(gè)指明了基于哪些列(也即基于哪些維度,包括切片維度)進(jìn)行讀??;n Set,保存了每列的限定值,對(duì)于一列而言,限定值可能會(huì)有多個(gè)(畢竟是批處理,一次請(qǐng)求多個(gè));n MeasureList,指明求取哪些度量值上的cell(度量值本質(zhì)是度量維上的限定值)。n BitKey,該batch的唯一索引。如圖所示的一個(gè)mdx查詢結(jié)果界面:此時(shí)會(huì)產(chǎn)生兩個(gè)batch,每個(gè)batch最終可能會(huì)產(chǎn)生若干segment,segment是cells的集合,segment數(shù)和度量值個(gè)數(shù)相同。n 一個(gè)batch是(其中“當(dāng)量數(shù)/適應(yīng)交通量=擁擠度”,擁擠度是計(jì)算成員),最終產(chǎn)生3個(gè)segment,每個(gè)segment只有一個(gè)cell: (地市=寧波市,measure=觀察里程) (地市=寧波市,measure=當(dāng)量數(shù)) (地市=寧波市,measure=適應(yīng)交通量)n 另一個(gè)batch是(其中的G310等是路線代碼,最終過濾掉空值后就剩下兩個(gè)了) ,最終產(chǎn)生3個(gè)segment,每個(gè)segment有多個(gè)cell: (地市=寧波市,roadId in (G310,G322,G210,S321.),measure=觀察里程) (地市=寧波市,roadId in (G310,G322,G210,S321.),measure=當(dāng)量數(shù)) (地市=寧波市,roadId in (G310,G322,G210,S321.),measure=適應(yīng)交通量)2、 2.5.3. RolapResult類RolapResult 是一個(gè)運(yùn)行中的請(qǐng)求的結(jié)果集。Mondiran的執(zhí)行結(jié)果由RolapResult類表單,由于mdx查詢語句本身就包含on rows(行軸上)、on columns(列軸上)和where部分(切片軸上),結(jié)果集中相對(duì)應(yīng)的為ROlapAxis對(duì)象,這其中有個(gè)sliceAxis對(duì)象。因此結(jié)果集是由若干ROlapAxis對(duì)象和一個(gè)RolapCell組構(gòu)成的。每個(gè)axis對(duì)象又由若干Position對(duì)象組成,每個(gè)Position對(duì)象又可能由若干member組成(注意一個(gè)postion會(huì)橫跨多個(gè)維度的成員)。注意ROlapAxis是抽象類,實(shí)際的對(duì)象類可能隨著不同的軸是不同的。如圖:圖中,column軸上兩個(gè)position(每個(gè)position含有一個(gè)成員),分別是: Measures.YJDMeasures.GCLCRow軸上有三個(gè)position(每個(gè)position含有二個(gè)成員),分別是:dimLX.All dimLXs, dimTime.All dimTimesdimLX.All dimLXs.寧波梁輝, dimTime.All dimTimesdimLX.All dimLXs.同江三亞, dimTime.All dimTimes切片軸上則有一個(gè)position:dimStation.All dimStations.寧波市單元值們則放置在RolapResult中的cellInfos對(duì)象里,屬CellInfoContainer接口,其中存放著CellInfo,并通過Cellkey進(jìn)行索引。CellKey:用于在maps里訪問cellinfo時(shí)使用的鍵值,根據(jù)cell的位置來決定鍵值。CellKey共有四個(gè)默認(rèn)實(shí)現(xiàn),及zero、one、two、three和many版的實(shí)現(xiàn),分別對(duì)應(yīng)著軸的個(gè)數(shù)。這些類中關(guān)鍵的屬性便是存儲(chǔ)各軸的位置值。CellInfo、CellInfoContainer:內(nèi)部類。CellInfo包含了一個(gè)cell所需要的所有信息(最關(guān)鍵的包含value值和一些formatter設(shè)置);最終將作為構(gòu)造ROlapCell對(duì)象的參數(shù)。CellInfoContainer顯然是cellInfo的容器,并使用CellKey來索引。ROlapCell:最終返回給jpivot的cell單元值。2.5.4. RolapEvaluator類最終負(fù)責(zé)在多維環(huán)境中執(zhí)行mdx表達(dá)式。該類中維護(hù)一個(gè)很重要的對(duì)象,即currentMembers,該上下文對(duì)象針對(duì)每個(gè)維度都包含了一個(gè)成員;通過setContext方法用來設(shè)置當(dāng)前維度,以開始計(jì)算當(dāng)前維度組合下的表達(dá)式值。2.5.5. 關(guān)于排序排序有單元值排序和維度成員排序兩種場景,但單元值排序優(yōu)先級(jí)更高,只有當(dāng)單元值排序相當(dāng)時(shí),才再對(duì)成員值進(jìn)行排序。單元值排序有六種,升序、降序、打破Hierarchy升序、打破Hierarchy降序、top count、bottom count。其中前四種參見:FunUtil.SortMembers()中的方法,這是總?cè)肟?,其中有BreakMemberComparator、HierarchicalMemberComparator、BreakArrayComparator、HierarchicalArrayComparator等排序器(Array包含多個(gè)member,此時(shí)相當(dāng)于cell上下文環(huán)境由多個(gè)維度參與)。對(duì)于array類排序,參見其中的public int compare(Member a1,Member a2)方法;對(duì)于單member類排序,參見其中的public int compareInternal(Membera1,Member a2)方法。維度成員排序似乎有三種:按照orderKey、按照ordinary、按照值(參見RolapMpareTo()方法,最終相當(dāng)于按字符串或數(shù)值比較,其中第三種內(nèi)部又會(huì)用到ascending屬性),這個(gè)是我們自己新增的屬性。具體參見FunUpareSiblingMembers()方法。2.6. 聚集層Star layer2.6.1. 概述包mondrian.rolap.agg,管理聚合緩存,這些緩存中包含著各單元格值。RolapStar中含有aggregation(聚合),一個(gè)aggregation是針對(duì)一組columns的,該聚合可以包含多個(gè)segment,同一個(gè)aggregation中的每個(gè)segment都將覆蓋到相同的列集合;每個(gè)segment表達(dá)了一組cell值,這些cell自然是由具體的列值和一個(gè)必備度量值(如下面的unit sales)來限定,如:(Unit sales, Gender = F, State in CA,OR, Marital Status = anything),由于其中的列值可能會(huì)取多個(gè),因此最終表達(dá)的cell值也可能是多個(gè)。RolapStar中有一個(gè)aggregations,是一個(gè)map對(duì)象,通過request的constrainedColumnsBitKey來索引一個(gè)aggregation。2.6.2. 聚合裝載過程實(shí)際中無論是底層的單元值還是聚合后的單元值都是放在聚合對(duì)象aggregation中的。以aggregation.load(colums,measures,predicates,pinnedSegments)為入口:n 參數(shù)中的除了measure不一樣外,其限定的列(colums)及列值(prediactes)都是一致的。因此轉(zhuǎn)換成對(duì)對(duì)若干segment的求值: Segment.load(segment,.),在該方法內(nèi)部: 首先根據(jù)segments中的信息生成sql查詢語句,有兩個(gè)不同的生成類:AggQuerySpec和SegmentArrayQuerySpec,前者用于找到聚合表情況下的sql語句生成,后者用于基于原始表的sql語句生成。具體可以參見它們的generateSqlQuery()方法,這里注意對(duì)以distinct count有不同的生成方法。Sql生成的核心類是sqlQuery,類似于交換系統(tǒng)中的QuerySqlFactory類。注意:聚合操作如avg、sum等都最終還是利用sql語句實(shí)現(xiàn)的,并非mondiran自己實(shí)現(xiàn)這些聚合功能。 利用jdbc,執(zhí)行sql語句,獲取到j(luò)dbc 結(jié)果集。參見mondrian.rolap.RolapUtil.executeQuery()方法。 解析結(jié)果集,將結(jié)果集中的數(shù)據(jù)填充到rows二維數(shù)值中,并且把各列的值也填充好。如圖:結(jié)果集每條記錄的值如寧波市、G010.,前面兩個(gè)是維度列值,后面幾個(gè)是度量值。各列的值(其中第0項(xiàng)值為:寧波市): 決定采用稀疏性(sparse)還是稠密性(dense)SegmentDataSet存儲(chǔ);并創(chuàng)建該空的DataSet對(duì)象。每個(gè)segment關(guān)聯(lián)一個(gè)DataSet對(duì)象;但其稀疏性還是稠密性都是一致的。注意dataset中單元值的個(gè)數(shù)可能是1個(gè)或多個(gè),是由各限定列的指定值個(gè)數(shù)乘積,若所有限定列都取單值,則顯然最終決定一個(gè)唯一的單元。 將上述的rows中間集轉(zhuǎn)換到SegmentDataSets集中。最后再分揀給每個(gè)segment,確保每個(gè)segment的setData(SegmentDataSet)被調(diào)用。n 若干排序:ValueColumnConstraintComparator2.6.3. segment詳解n 下圖是有兩個(gè)限定列的兩個(gè)segment的描述(注:其中roadid列雖然指定了8個(gè)候選值,但由于使用了空行/列過濾,最后只剩下兩個(gè)路線有值,故最后segment結(jié)果集的單元數(shù)也只有兩個(gè),對(duì)應(yīng)于G010和G318的):其中第二個(gè)對(duì)應(yīng)的dataset為:317.769, 120.604對(duì)應(yīng)的透視界面為(參見其中的“觀測(cè)里程”度量值,與上面的dataset一致):n 再譬如有三個(gè)限定列的segment描述,它們位于另一個(gè)aggreation對(duì)象中:(其中timeId列的any代表所以可能的時(shí)間值,共有20032005三個(gè)年,所以最終該segment共有3個(gè)cell值)對(duì)應(yīng)的dataset為:129.910, 129.909, 57.950對(duì)應(yīng)的透視界面為(顯然該aggreation還有另外一個(gè)segment,其中的roadId對(duì)應(yīng)于G010寧波梁輝):n 再譬如維度中有多個(gè)層次的情況時(shí),一個(gè)維度會(huì)對(duì)應(yīng)多個(gè)列:Query query = connection.parseQuery(SELECT + Time.1997, + Time.1997.Children ON COLUMNS, + Customer.USA, + Customer.USA.OR, + Customer.USA.WA ON ROWS +FROM Sales);Result result = connection.execute(query);該語句執(zhí)行后產(chǎn)生的segment分別為(除了第一個(gè)外,其他segment都會(huì)包含多個(gè)cell,因?yàn)樗鼈兊南薅兄泻卸嘀档那闆r):Segment YN#1Year Nation Unit Sales1997 USA xxxPredicates: Year=1997, Nation=USASegment YNS#1Year Nation State Unit Sales1997 USA OR xxx1997 USA WA xxxPredicates: Year=1997, Nation=USA, State=OR, WASegment YQN#1Year Quarter Nation Unit Sales1997 Q1 USA xxx1997 Q2 USA xxxPredicates: Year=1997, Quarter=any, Nation=USASegment YQNS#1Year Quarter Nation State Unit Sales1997 Q1 USA OR xxx1997 Q1 USA WA xxx1997 Q2 USA OR xxx1997 Q2 USA WA xxxPredicates: Year=1997, Quarter=any, Nation=USA, State=OR, WA2.6.4. 緩存失效控制為了提高訪問效率,必須要使用緩存;但使用緩存必須在數(shù)據(jù)庫底層數(shù)據(jù)發(fā)生變化時(shí)做好數(shù)據(jù)的失效和刷新工資。老版的做法非常粗略:mondrian.rolap.RolapSchema.clearCache();這意味著連mondrian schema都被失效,與之關(guān)聯(lián)的全部緩存也都被失效。新版的做法是引入了mondrian.olap.CacheControl接口,可以很精細(xì)地由應(yīng)用控制緩存。為此mondrian引入了cell region的概念,region是由一個(gè)或多個(gè)成員定義出的多維空間(定義時(shí)可以指定是否包含這些成員的子成員)。為了使緩存失效,你需要首先定義一個(gè)region,然后告訴mondrian失效該region內(nèi)的所有cells;為了確保一致性,mondrian還會(huì)自動(dòng)地把這些cell的聚合單元也一起失效。具體參見CacheControl.CellRegion類。最終調(diào)用cacheControl.flush(cellRegion)。具體失效時(shí),還是針對(duì)segment進(jìn)行的,因?yàn)閙ondiran中的cell緩存是通過segment組織的。失效發(fā)生時(shí),可能segment中的部分cell無用了,但mondrian并不會(huì)真正刪除這些cell,而是strengthened其predicates,例如失效前的某個(gè)segment為:1997 USA OR xxx1997 USA WA xxxPredicates: Year=1997, Nation=USA, State=OR, WA然后Crossjoin(time.1997.Q2,Customer.USA.OR)的cellRegion失效,此時(shí)該segment變?yōu)椋?997 USA OR xxx1997 USA WA xxxPredicates: Year=1997, Nation=USA, State=WA目前這樣處置未必最合理,因?yàn)闀?huì)有內(nèi)存泄露。將來可能根據(jù)該segment中的cell達(dá)到一定的失效閥值,就徹底把該segment拋棄掉。Segment的合并也是將來應(yīng)考慮的事情,以減少segment碎片。維度成員值的緩存控制目前mondrian還未提供控制接口。但是metaCacheControl,例如控制schema xml等還是提供不少接口了,例如:l mondrian.rolap.RolapSchema.clearCache() l mondrian.olap.MondrianServer.flushSchemaCache() l mondrian.rolap.cache.CachePool.flush() l mondrian.rolap.RolapSchema.flushRolapStarCaches(boolean) 該方法不失效schema,但失效緩存,在應(yīng)用層還不想使用cellRegion失效緩存前,可以適度使用。l mondrian.rolap.RolapSchema.flushAllRolapStarCachedAggregations() l mondrian.rolap.RolapSchema.flushSchema(String,String,String,String) l mondrian.rolap.RolapSchema.flushSchema(DataSource,String) 3. 交互管理層MondrianModel 是JPivot中用來展現(xiàn)一個(gè)MDX查詢的所有原數(shù)據(jù)的模型。這里主要講MondrianModel的三個(gè)方法,initialize(),getResult(),destroy()。3.1. 初始化MondrianModel1、 在jpivot.mondrian.MondrianModel執(zhí)行initialize()方法之前,先用MondrianModelFactory.Config對(duì)象為MondrianModel對(duì)象設(shè)置jdbc,schema url等參數(shù)。2、 調(diào)用mondrian.olap.DriveManager.getConnection()方法,創(chuàng)建并返回mondrian.rolap.RolapConnection對(duì)象,置于變量monConnection中;創(chuàng)建連接的參數(shù)指定詳見mondrian.olap.RolapConnectionProperties。2.1 在創(chuàng)建RolapConnection對(duì)象的構(gòu)造函數(shù)中,會(huì)用對(duì)象池技術(shù)建立mondrian.rolap.RolapSchema對(duì)象。該對(duì)象會(huì)被緩存在對(duì)象池中,只會(huì)創(chuàng)建一次(RolapSchema對(duì)象中還有一個(gè)大對(duì)象xmlSchema,是純定義性質(zhì)的,Mondrian.olap.MondrianDef.Schema);這里需要注意的是:n RolapSchema對(duì)象的建立有幾種方法:首先schema字符串內(nèi)容本身可以通過參數(shù)直接傳遞進(jìn)來;也可以通過url地址指定;還可以通過自定義的DynamicSchemaProcessor類來給定(這樣就有機(jī)會(huì)動(dòng)態(tài)對(duì)schena內(nèi)容進(jìn)行修改)。n RolapSchema對(duì)象本身的建立一般是從緩存中讀取,沒有時(shí)則創(chuàng)建。但若使用了上述的DynmicSchemaProcessor則每次都會(huì)重新創(chuàng)建;并且若指定了UseContentChecksum參數(shù) (將使用md5對(duì)字符串內(nèi)容編碼),若UseContentChecksum為true,則 md5編碼值與以前的不同,則即使存在了RolapSchema對(duì)象也會(huì)重新創(chuàng)建??膳cDynamicSchemaProcessor屬性一起用。n 在Mondrian新版本3.0中,RolapConnectionProperties 中除了定義了DynamicSchemaProcessor 和UseContentChecksum 參數(shù),還新增了UseSchemaPool屬性,如果該屬性為false,將禁用schema緩存。2.2 最后調(diào)用RolapSchema.createRole()方法創(chuàng)建該連接關(guān)聯(lián)的role對(duì)象(如果指定了的話);并創(chuàng)建ROlapSchemaReader對(duì)象(和role綁定的,讀取時(shí)會(huì)進(jìn)行必要的控制)。2.3 根據(jù)傳入的參數(shù)設(shè)置locale,沒有的話按照en處理。3、調(diào)用connection的parseMDX(),最終調(diào)用ConnectionBase.parseQuery()方法準(zhǔn)備好一個(gè)mondrian.olap.Query對(duì)象,置入成員變量monQuery;query對(duì)象由mondrian.olap.parse對(duì)象生成,該對(duì)象是一個(gè)自動(dòng)生成的類,使用了javacup技術(shù)。3.2. 獲取結(jié)果集1、 之前確保MondiranModel中的monQuery對(duì)象已經(jīng)創(chuàng)建好。2、 Jpivot中,界面會(huì)調(diào)用jpivot.table.TableCompont對(duì)象的render方法進(jìn)行繪制,最終會(huì)調(diào)用MondrianModel.getResult()的方法,但返回的是jpivot.olap.model.Result對(duì)象,并非mondrian.olap.Result對(duì)象。2.1 首先執(zhí)行MondrianQueryAdapter對(duì)象queryAdapter的onExecute()。得到mdx語句。2.2 調(diào)用monConnection.execute(monQuery)獲取mondrian result對(duì)象;內(nèi)部會(huì)創(chuàng)建 new ROlapResult(monQuery,true),RolapResult得到的是運(yùn)行中請(qǐng)求的結(jié)果,其中ture代表要實(shí)際裝載數(shù)據(jù)。2.3 內(nèi)部會(huì)進(jìn)行Evaluator算法:顯式成員:在軸上的成員。隱式成員:不在軸上的成員,可能是在函數(shù)中。如果一個(gè)維度的成員都是隱式成員,相當(dāng)于在切片上使用默認(rèn)成員。有兩種特定維度:時(shí)間維度和度量維度。時(shí)間維度度量維度的默認(rèn)成員是沒有所有的的,約定成俗的是第一個(gè)度量。首先,RolapEvaluator會(huì)被創(chuàng)建。創(chuàng)建過程中,它會(huì)從每個(gè)hierarchy中獲取一個(gè)member,每個(gè)member是hierarchy的默認(rèn)成員。對(duì)于大多數(shù)hierarchy,這個(gè)默認(rèn)成員就是所有成員??赡苡袃煞N例外:1)hierarchy沒有所有成員;2)hierarchy有所有成員但是它不是默認(rèn)成員。這樣的話,默認(rèn)成員仍然會(huì)被使用,但是可能會(huì)有問題。然后載入所有無所有成員的hierarchy的根成員,載入非默認(rèn)成員的所有的成員。2.4 內(nèi)部會(huì)進(jìn)行Evaluator算法,三大步驟:n Determine axes步驟:決定每個(gè)軸上的所有成員,但此時(shí)還不保存信息(不創(chuàng)建RolapAxis)。確定切片軸上的成員。軸上發(fā)現(xiàn)的成員都會(huì)被加入到AxisMember中。如果該成員是度量,則切片指明請(qǐng)求的度量,并將該度量放入evaluator的context中(取代cube中的第一個(gè)度量,即默認(rèn)度量)。其它的切片成員也會(huì)被放入evaluator的context的。n execute axes步驟:為每個(gè)軸保存所有成員,創(chuàng)建RolapAxis對(duì)象(重復(fù)了第一步驟,只是此時(shí)創(chuàng)建了RolapAxis對(duì)象,該對(duì)象是結(jié)果集中的維度成員值部分)。執(zhí)行第一步和第二步時(shí)確保數(shù)據(jù)已經(jīng)載入。n get cell步驟:根據(jù)軸上的成員值計(jì)算并存儲(chǔ)每個(gè)單元值(結(jié)果集的cell值部分),參見executeBody()方法,內(nèi)部主要調(diào)用executeStripe()方法, ExecuteStripe()方法內(nèi)部采用遞歸方法依次獲取每個(gè)單元值,從行軸開始(軸位置索引最大的那個(gè)),針對(duì)每個(gè)行軸的mondrian.olap.position進(jìn)行循環(huán),在一個(gè)循環(huán)內(nèi)再針對(duì)列軸的每個(gè)position進(jìn)行循環(huán),求得交叉點(diǎn)的cell值。每個(gè)position由一個(gè)或多個(gè)維度成員值組成,具體的個(gè)數(shù)同該軸上交叉的維度數(shù);在計(jì)算某cell值之前,會(huì)依次用該cell的member值(包括切片上的維度值)設(shè)置好evaluator的context。最后調(diào)用evaluator.evaluateCurrent()方法獲得當(dāng)前context下的cell值。 Evaluator.evaluat

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論