发布时间 : 星期日 文章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