mondrian源码分析与说明 联系客服

发布时间 : 星期日 文章mondrian源码分析与说明更新完毕开始阅读bf3b867f2e3f5727a5e96245

对于单member类排序,参见其中的public int compareInternal(Membera1,Member a2)方法。

维度成员排序似乎有三种:按照orderKey、按照ordinary、按照值(参见RolapMember.compareTo()方法,最终相当于按字符串或数值比较,其中第三种内部又会用到ascending属性),这个是我们自己新增的属性。具体参见FunUtil.compareSiblingMembers()方法。

2.6. 聚集层Star layer

2.6.1. 概述

包mondrian.rolap.agg,管理聚合缓存,这些缓存中包含着各单元格值。

RolapStar中含有aggregation(聚合),一个aggregation是针对一组columns的,该聚合可以包含多个segment,同一个aggregation中的每个segment都将覆盖到相同的列集合;每个segment表达了一组cell值,这些cell自然是由具体的列值和一个必备度量值(如下面的unit sales)来限定,如:(Unit sales, Gender = 'F', State in {'CA','OR'}, Marital Status = anything),由于其中的列值可能会取多个,因此最终表达的cell值也可能是多个。RolapStar中有一个aggregations,是一个map对象,通过request的constrainedColumnsBitKey来索引一个aggregation。

2.6.2. 聚合装载过程

实际中无论是底层的单元值还是聚合后的单元值都是放在聚合对象aggregation中的。以aggregation.load(colums,measures,predicates,pinnedSegments)为入口:

? 参数中的除了measure不一样外,其限定的列(colums)及列值(prediactes)都是一

致的。因此转换成对对若干segment[]的求值: Segment.load(segment[],….),在该方法内部:

? 首先根据segments中的信息生成sql查询语句,有两个不同的生成类:

AggQuerySpec和SegmentArrayQuerySpec,前者用于找到聚合表情况下的sql语句生成,后者用于基于原始表的sql语句生成。具体可以参见它们的generateSqlQuery()方法,这里注意对以distinct count有不同的生成方法。Sql生成的核心类是sqlQuery,类似于交换系统中的QuerySqlFactory类。注意:聚合操作如avg、sum等都最终还是利用sql语句实现的,并非mondiran自己

实现这些聚合功能。

? 利用jdbc,执行sql语句,获取到jdbc 结果集。参见

mondrian.rolap.RolapUtil.executeQuery()方法。

? 解析结果集,将结果集中的数据填充到rows[][]二维数值中,并且把各列的值

也填充好。如图:

结果集每条记录的值如宁波市、G010….,前面两个是维度列值,后面几个是度量值。

各列的值(其中第0项值为:[宁波市]):

? 决定采用稀疏性(sparse)还是稠密性(dense)SegmentDataSet存储;并创建该

空的DataSet对象。每个segment关联一个DataSet对象;但其稀疏性还是稠密性都是一致的。注意dataset中单元值的个数可能是1个或多个,是由各限定列的指定值个数乘积,若所有限定列都取单值,则显然最终决定一个唯一的单元。

? 将上述的rows中间集转换到SegmentDataSets集中。最后再分拣给每个

segment,确保每个segment的setData(SegmentDataSet)被调用。

? 若干排序:ValueColumnConstraintComparator

2.6.3. segment详解

? 下图是有两个限定列的两个segment的描述(注:其中roadid列虽然指定了8个候选

值,但由于使用了空行/列过滤,最后只剩下两个路线有值,故最后segment结果

集的单元数也只有两个,对应于G010和G318的):

其中第二个对应的dataset为:

[317.769, 120.604]

对应的透视界面为(参见其中的“观测里程”度量值,与上面的dataset一致):

? 再譬如有三个限定列的segment描述,它们位于另一个aggreation对象中:(其中

timeId列的any代表所以可能的时间值,共有2003~2005三个年,所以最终该segment共有3个cell值)

对应的dataset为:

[129.910, 129.909, 57.950]

对应的透视界面为(显然该aggreation还有另外一个segment,其中的roadId对应于G010—宁波梁辉):

? 再譬如维度中有多个层次的情况时,一个维度会对应多个列:

Query query = connection.parseQuery( \

\

\ \ \

\ \

Result result = connection.execute(query);

该语句执行后产生的segment分别为(除了第一个外,其他segment都会包含多个cell,因为它们的限定列中含有多值的情况):

Year Nation Unit Sales Segment 1997 USA xxx YN#1 Predicates: Year=1997, Nation=USA Year Nation State Unit Sales Segment 1997 USA OR xxx YNS#1 1997 USA WA xxx Predicates: Year=1997, Nation=USA, State={OR, WA} Year Quarter Nation Unit Sales Segment 1997 Q1 USA xxx YQN#1 1997 Q2 USA xxx Predicates: Year=1997, Quarter=any, Nation=USA Year Quarter Nation State Unit Sales 1997 Q1 USA OR xxx Segment 1997 Q1 USA WA xxx YQNS#1 1997 Q2 USA OR xxx 1997 Q2 USA WA xxx