为了知足业务管理和决策的报表系统(包括传统报表、数据仓库、OLAP等)也被建立出来,企业主管经过报表了解企业的整体运行状态。
可是,随着企业间竞争的加重和市场节奏的进一步加快,企业的平常管理须要对关键业务指标的更加实时的监控和反馈。好比:制造业须要更及时的仓库调度、金融业须要更实时的风险防范、电信业须要更及时的服务指标监控。因而,愈来愈多的企业提出实时企业的要求,传统的ERP等信息系统和报表系统没法知足这些需求。实时业务监控解决方案旨在更好支撑客户此类需求。
http://www.tuicool.com/articl...
当今的数据处理大体能够分红两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、平常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操做,侧重决策支持,而且提供直观易懂的查询结果。php
OLAP技术很是多的特性,归纳起来主要有以下几点特性:html
OLAP技术是面向分析人员、管理人员的;java
OLAP技术对数据访问一般是只读的,而且一次访问大量数据;sql
OLAP技术是面向主题的多维数据分析技术。数据库
OLAP(On-Line Analysis Processing)在线分析处理是一种共享多维信息的快速分析技术;
OLAP利用多维数据库技术使用户从不一样角度观察数据;OLAP用于支持复杂的分析操做,侧重于对管理人员的决策支持,能够知足分析人员快速、灵活地进行大数据复量的复杂查询的要求,而且以一种直观、易懂的形式呈现查询结果,辅助决策。
上面是OLAP的一些不一样的解释,本文将从如下几个方面介绍OLAP。express
http://www.huqiwen.com/2012/0...
Cube立方体的概念:数组
在Bi领域,cube是一个很是重要的概念,是多维立方体的简称,主要是用于支持联机分析应用(OLAP),为企业决策提供支持。Cube就像一个坐标系,每个Dimension表明一个坐标系,要想获得一个一个点,就必须在每个坐标轴上取得一个值,而这个点就是Cube中的Cell。
Cube是联机分析的关键。他们是一种多维结构,包含原始事实数据、聚合数据,这些数据聚合容许用户快速进行复杂的查询,Mdx语言就应用它更是如鱼得水。
Cube包含两个基本概念:维度和度量缓存
维度(Dimension):维度提供了分类描述,表示一类分析角度,用户经过维度分析度量数据。好比上图中的三个维度:时间、产品、地域性能优化
度量(Measures):度量表示用来聚合分析的数字信息,度量的集合组合成了一个特殊的维度。如数量、销售额等。服务器
级别(Level):一个维度上能够包含的层次结构,表示特定的分类。如上图中地域维度能够包含的级别层次级:国家、省、市;时间维度包含的级别层次包含:年、季度、月、日等。
成员,是最重要的概念之一,一个成员是维度(包括度量<Measures>)上的项目值。如上图时间维度上”年“级别的成员就包含:2000,2001,2002,2003...月成员包含:一、二、3等。
计算成员,是一种运行经过特殊表示式动态计算的成员。也就造成了度量(Measures)的结果。计算成员不影响现有的Cube数据,它基于cube数据,经过各类数学表达式和各类函数定义,能够建立复杂的表达式。任何动态分析功能,均可以经过计算成员实现,好比实现占比,同期比等等。
维度的概念
例如一个维度(Dimension):Region
该维度下有四个级别(Levels):country、province、city、county,他们属于层次集合(Hierarchy)
经过维度和级别咱们能够定义一个元素(Member)如:
Region.Levels(1).members(2)=china
Region.Levels(2).members(3)=shanghai
http://www.cnblogs.com/zhijia...
2、 OLAP的基本概念
(1)度量、指标)
是数据度量的指标,是数据的实际意义,即描述数据“是什么”。像上面示例中的人数。
(2)维度
维度是描述与业务主题相关的一组属性,单个属性或属性集合能够构成一个维。如上面示例中的学历、民族、性别等都是维度。
(3)维的层次
一个维每每能够具备多个层次,例如时间维度分为年、季度、月和日等层次,地区维能够是国家、地区、省、市等层次。这里的层次表示数据细化程度,对应概念分层。后面介绍的上钻操做就是由低层概念映射到高层概念。概念分层可除根据概念的全序和偏序关系肯定外,还能够经过对数据进行离散化和分组实现。
(4)维的成员
若维是多层次的,则不一样的层次的取值构成一个维成员。部分维层次一样能够构成维成员,例如“某年某季度”、“某季某月”等均可以是时间维的成员。
(5)多维数组
多维数组用维和度量的组合表示。一个多维数组能够表示为(维1,维2,……,维n,变量),例如(部门,职系、民族、性别,人数)组成一个多维数组。
(6)数据单元(单元格)
多维数组的取值。当多维数组中每一个维都有肯定的取值时,就惟一肯定一个变量的值。数据单元能够表示为(维1成员,维2成员,……,维N成员,变量的值),例如(人事教育部,技能,回族,男,1人)表示一个数据单元,表示人事教育部职系是技能的回族男性有1人。
(7)事实
事实是不一样维度在某一取值下的度量,例如上述人事教育部职系是技能的回族男性有1人就表示在部门、职系、民族、性别四个维度上企业人数的事实度量,而且在为人数事实中包含部门维度人事教育部这一个维度层次,若是将人数事实的全部维度考虑在内,就构成有关人数的多维分析立方体。
3、 OLAP的特色
电子数据表与OLAP相比,不具有OLAP的多维性、层次、维度计算以及结构与视图分离等特色。
多维。维是OLAP的核心概念,多维性是OLAP的关键属性,这与数据仓库的多维数据组织正好相互补充。为了使用户可以从多个维度、多个数据粒度查看数据,了解数据蕴含的信息,
系统须要提供对数据的多维分析功能,包括切片、旋转和钻取等多种操做
4、 OLAP的操做
OLAP比较经常使用的操做包括对多维数据的切片与切块、上钻(drill-up)与下钻(drill-down)如下旋转(rotate)等。此外,OLAP还能对多维数据进行深加工。
OALP的这些操做使用户可以从多个视角观察数据,并以图形、报表等多种形式展现,从而获取隐藏在数据中的信息。
(1)切片与切块。
选定多维数组的一个维成员作数据分割的操做称为该维上的一个切片。一般把多维数组中选定一个二维子集的操做视为切片,假设选定的维i上的某个维成员Vi,则此多维数组子集能够定义为(维V1……,维Vi,维N,变量)。当某维只取一个维成员时,便获得一个切片,而切块则是某一维取值范围下的多个切片的叠合。经过对数据立方体的切片或切块分割,能够从不一样的视角获得各类数据。
(2)钻取
钻取包括上钻和下钻。争取可以帮助用户得到更多的细节性数据,逐层的分析问题的所在和缘由。
上钻又称为上卷(roll-up)。上钻操做是指经过一个维的概念分层向上攀升或者经过维归约在数据立方体上进行数据汇总。例如在上面的示例中,能够按学历汇总数据,如把各类学历的都归约为全部学历,即可以获得沿学历维上钻的数据汇总。
下钻是上钻的逆操做,经过对某一汇总数据进行维层次的细分(沿维的概念分层向下)分析数据。下钻使用用户对数据可以得到更深刻的了解,更容易发现问题本质,从而作出正确的决策。
钻取使用户不会再被海量的数据搞得晕头转向:上钻让用户站在更高层次观察数据,下钻则能够细化到用户所判决的详细数据。钻取的尝试与维度与维所划分的层次相对应,根据用户关心的数据粒度合理划分。
(3)旋转
旋转又称转轴,是一种视图操做,经过旋转变换一个报告或页面显示的维度方向,在表格中从新安排维的位置,例如行列转换。这种对立方体的重定位能够获得不一样视角的信息。
(4)其余OLAP操做
除以上经常使用多维操做外,还有其余多维操做。
钻过(drill-across)。钻过操做涉及多个事实表的查询并把结果合并为单个数据集,一个典型的例子就是预测数据与当前数据的结合:一般预测数据与当前数据存在于不一样的表中,当用户比较预测销售与当月销售时,须要跨多个事实表查询。
钻透(drill-through)。钻透使用关系SQL,查询数据立方体的底层,一直到后羰的关系表。
5、 OLAP的分类
OLAP分类
按处理方式分类
Server OLAP:绝大多数的OLAP系统都属于此类,Server OLAP在服务端的数据库上创建多维数据立方体,由服务端提供多维分析,并把最终结果呈现给用户
Client OLAP:所相关立方体数据下载一本地,由本地为用户提供多维分析,从而保证在网络故障时仍然能正常工做。
按存储方式分类
ROLAP。ROLAP使用关系数据库或扩充关系数据库(XRDBMS)存储管理数据仓库,以关系表存储多维数据,有较强的可伸缩性。其中维数据存储在维表中,而事实数据和维ID则存储在事实表中,维表和事实表经过主外键关联。
MOLAP。MOLAP支持数据的多维视图,采用多维数据组存储数据,它把维映射到多维数组的下标或下标的范围,而事实数据存储在数组单元中,从而实现了多维视图到数组的映射,造成了立方体的结构。大容量的数据使立方体稀疏化,此时须要稀疏矩阵压缩技术处理,因为MOLAP是从物理上实现,故又称为物理OLAP(Physical OLAP)。
DOLAP。DOLAP是属于单层架构,它是基于桌面的客户端OLAP,主要特色是由服务器生成请求数据相关的立方体并下载到本地,由本地提供数据结构与报表格式重组,为用户提供多维分析,此时无需任何的网络链接,灵活的存储方式方便了移动用户的需求,但支持数据有限,使用范围有限。
~/Desktop/Mondrian数据分析学习.pdf
http://mondrian.pentaho.com/d...
http://www.cnblogs.com/panfen...
在Mondrian里面的cube是以XML的形式定义的。(MDX)
Mondrian自己是不存储数据的,经过MDX语句(一个相似于SQL的查询语言)来获取数据,Mondrian 运行的时候要连数据库,而且还要有一个数据模型配置文件(Mondrian叫schema),其实就是一个取数据的规则;由此可知Mondrian只不过是把MDX 翻译成了SQL而后从数据库中把数据拿出来给用户
Mondrian是一个开放源代码的Rolap服务器,使用java开发的。它实现了xmla和jolap规范,并且自定义了一种使用mdx语言的客户端接口。Mondrian是olap服务器,而不是数据仓库服务器,所以Mondrian的元数据主要包括olap建模的元数据,不包括从外部数据源到数据库转换的元数据。也就是说Mondria的元数据仅仅包括了多维逻辑模型,从关系型数据库到多维逻辑模型的映射,存取权限等信息。在功能上,Mondrian支持共享维和成员计算,支持星型模型和雪花模型的功能。
Mondrian 是一个开源项目,是开源项目Pentaho的一部分,是一个用Java写成的OLAP引擎。它实现了MDX语言、XML解析、JOLAP规范。
它从RDBMS和其它数据源读取数据并把数据汇集在内存缓存中,而后通过Java API用多维的方式对结果进行展现,同时能够不写SQL就能分析存储于SQL 数据库的庞大数据集,能够封装JDBC数据源并把数据以多维的方式展示出来。
总体的项目架构,四个大部分Schema manager、Session Manager、Dimension Manager、Aggregate Manager
Schema Manager:与初始化紧密相关。主要是一些重要的数据结构如缓存池的构建以及多维模型的生成。
Session Manager:最为重要的一个部分。接受MDX查询、解析MDX,返回结果。
Aggregate Manager:实现了对汇集表的管理。主要是对OLAP缓存的管理,属于性能优化的部分。
Dimension Manager:维度的管理。实现多维模型中维度和关系数据库表中列的映射,在Schema Manager也有部分功能处理这些映射。
Mondrian经过Schema来定义一个多维数据库,它是一个逻辑概念上的模型,其中包含Cube(立方体)、Dimension(维度)、Hierarchy(层次)、Level(级别)、Measure(度量),这些被映射到数据库物理模型。Mondrian中Schema是以XML文件的形式定义的。
Cube(立方体)由维度构建出来的多维空间,是一系列Dimension和Measure的集合区域,它们共用一个事实表。
Dimension(维度)观察数据的一种角度,维度能够理解为立方体的一个轴。是一个Hierarchy的集合,维度通常有其相对应的维度表,它由Hierarchy(层次)组成,而Hierarchy(层次)又是由组成Level(级别)的。
Hierarchy(层次)是指定维度的层级关系的,若是没有指定,默认Hierarchy里面装的是来自立方体中的真实表。
Level(级别)是Hierarchy的组成部分,使用它能够构成一个结构树,Level的前后顺序决定了Level在结构树上的位置,最顶层的 Level 位于树的第一级,依次类推。
Measure(度量)是咱们要进行度量计算的数值,支持的操做有sum、count、avg、distinct-count、max、min等。
在多维分析中,关注的内容一般被称为度量(Measure),而把限制条件称为维度(Dimension)。
多维分析就是对同时知足多种限制条件的全部度量值作汇总统计。包含度量值的表被称为事实表(Fact Table),描述维度具体信息的表被称为维表(Dimension Table)
立方体:由维度构建出来的多维空间,包含了全部要分析的基础数据,全部的聚合数据操做都在立方体上进行。
维度:就是观察数据的一种角度。在这个例子中,路线,源,时间都是维度,
维度成员:构成维度的基本单位。对于时间维,例如它的成员分别是:第一季度、第二季度、第三季度、第四季度。
层次:维度的层次结构,要注意的是存在两种层次:天然层次和用户自定义层次。对于时间维而言,(年、月、日)是它的一个层次,(年、季度、月)是它的另外一个层次,一个维能够有多个层次,层次能够理解为单位数据聚合的一种路径。
级别:级别组成层次。对于时间维的一个层次(年、月、日)而言,年是一个级别,月是一个级别,日是一个级别,显然这些级别是有父子关系的。
度量值:要分析展现的数据,即指标。如图1中一个cell中包含了两个度量值:装箱数和截至时间,能够对其进行多维分析。
事实表:存放度量值的表,同时存放了维表的外键。全部的分析用的数据最终都是来自与事实表。
维表:一个维度对应一个或者多个维表。一个维度对应一个维表时数据的组织方式就是采用的星型模式,对应多个维表时就是采用雪花模式。雪花模式是对星型模式的规范化。简言之,维表是对维度的描述。
MDX查询:多维模型的查询语言MDX(MDX是微软发布的多维查询语言标准),它的语法与SQL有不少类似之处:select {[Measures].[Salary]} on columns, {[Employee].[employeeId].members} on rows from CubeTest对于这条语句,COLUMNS 和 ROWS都表明查询轴,其中COLUMNS表明列轴,ROWS表明行轴。COLUMNS又能够写成0,ROWS又能够写成1,当只有两个查询轴时,能够理解为结果的展示格式是一个平坦二维表。这条语句的含义就是查询名字为CubeTest的立方体,列显示Measures维度的salary,行显示 Employee维度employeeId级别的全部成员,那么得出的结果就是employeeId全部成员的salary,也就是全部员工的薪酬。具体语法规范和帮助文档能够参考微软的用户文档。
百万级事实数据:按照Mondrian文档中所描述的内容能够看出,只基于操做系统环境和数据库环境的优化,Mondrian Server在百万行级别数据量的事实表(关系数据库)仍可以运行良好。固然这须要咱们本身来评测和证明。
千万级事实数据:当事实表数据立方体的数据量达到千万行以上时,Mondrian建议采用“汇总表”或者是由数据库支持的相似Oracle数据库的“物化视图”功能来优化OLAP查询的性能。
Mondrian缓存设置:因为Mondrian会将查询过的数据缓存起来,因此Mondrian建议缓存的大小根据具体项目的实际状况判断,固然是缓存越大越好
为了提升海量数据下的查询响应速度,Mondrian自动将首次查询的结果缓存到内存中,以后的查询若是命中缓存内容,则再也不访问数据库。这种实现方式有点自没必要说,
可是在实现实时OLAP时会存在问题,实时OLAP中数据变化频繁致使缓存中的数据不是最新的。
缓存控制接口:为了作到不重启OLAP Server也能更新缓存,Mondrian提供了一系列的刷新缓存的接口,支持指定清除指定schema的元数据缓存、查询结果缓存;清除动做能够是所有清除 也能够是 部分清除(能够指定清除某个维度下某级别成员的相关内容)。
数据变化监听: Mondrian提供了缓存控制接口(被动响应),但对于实现咱们的目标“实时OLAP”来讲咱们就须要本身实现一个数据变动监听的模块,来监听数据变化,一旦数据有变化就发起变动事件,更新Mondrian引擎的缓存。目前初步考虑实现方案为ETL工具在数据处理结束后通知OLAP引擎。引擎收到数据变动通知后作清理缓存的动做。
Jpivot:简单说是一个展现工具,有人说是个标签库,相似于struts。只是用来显示mondrian传来的xml数据,将其渲染成咱们熟悉的html。对于层次性很强的报表,XML渲染的确有他的魅力,免去了繁杂的js痛苦。总之mondrian是用来研究和提取数据,jpivot是用来显示数据。至于jpivit是如何显示数据,主要是经过xls+xml。 Jpivot自己的界面是很难看的。
Pentaho、Saiku、Jpivot都用到了Mondrian作为其多维数据处理的服务器,网上的不少关于Mondrian的文章也都是以Jpivot来进行分析的,
不过Jpivot已经被抛弃了做者也再也不更新了,而且Jpivot只能支持到Mondrian3.5 因此对于新版本的Mondrian必定是不能用Jpivot了(不过Jpivot有一个替代品Pivot4j这个还在持续维护),
这里仍是推荐你们用Saiku或者Pivot4j
若是咱们不想用Saiku、pivot4j 这样现成的东西(毕竟有不少东西咱们用不到)那么能够把Mondrian 集成到咱们本身的应用中去
http://mondrian.pentaho.com/d...
personDemo.xml
<?xml version="1.0" encoding="UTF-8"?> <Schema name="Mondrian"> <!--模型定义--> <Cube name="Person"> <!--立方体 ,一个立方体有多个维度--> <Table name="PERSON" /> <!--立方体对应的表 --> <Dimension name="部门" foreignKey="USERID" > <!--定义维度 --> <Hierarchy hasAll="true" primaryKey="USERID" allMemberName="全部部门" > <!--定义维度下面的层次,层次包含不少层 --> <Table name="PERSON" alias="a"/> <!--定义维度获取数据的来源-表 --> <Level name="部门" column="DEPARTMENT" uniqueMembers="true" /> <!--定义层次的层,每一个层对应数据库中对应的字段 --> <Level name="姓名" column="USERNAME" uniqueMembers="true" /> </Hierarchy> </Dimension> <Dimension name="性别" foreignKey="USERID" > <Hierarchy hasAll="true" primaryKey="USERID" allMemberName="全部性别"> <Table name="PERSON" alias="b" /> <Level name="性别" column="SEX" uniqueMembers="true" /> </Hierarchy> </Dimension> <Dimension name="专业技术资格类别" foreignKey="USERID" > <Hierarchy hasAll="true" primaryKey="USERID" allMemberName="全部专业技术资格类别"> <Table name="PERSON" alias="c" /> <Level name="资格类别" column="ZYJSLB" uniqueMembers="true" /> </Hierarchy> </Dimension> <Dimension name="专业技术资格等级" foreignKey="USERID" > <Hierarchy hasAll="true" primaryKey="USERID" allMemberName="全部专业技术资格等级"> <Table name="PERSON" alias="d" /> <Level name="资格等级" column="ZYJSDJ" uniqueMembers="true" /> </Hierarchy> </Dimension> <Dimension name="职系" foreignKey="USERID" > <Hierarchy hasAll="true" primaryKey="USERID" allMemberName="全部职系"> <Table name="PERSON" alias="e" /> <Level name="职系" column="ZHIXI" uniqueMembers="true" /> </Hierarchy> </Dimension> <Dimension name="民族" foreignKey="USERID" > <Hierarchy hasAll="true" primaryKey="USERID" allMemberName="全部民族"> <Table name="PERSON" alias="f" /> <Level name="民族" column="NATIONALITY" uniqueMembers="true" /> </Hierarchy> </Dimension> <Dimension name="学历" foreignKey="USERID" > <Hierarchy hasAll="true" primaryKey="USERID" allMemberName="全部学历"> <Table name="PERSON" alias="g" /> <Level name="学历" column="XUELI" uniqueMembers="true" /> </Hierarchy> </Dimension> <Measure name="人数" column="USERID" aggregator="distinct count" /> <!--指标/度量,采用distinct count聚合 --> </Cube> </Schema>
对应表:
CREATE TABLE `person` ( `userid` varchar(100) , `department` varchar(100) , `username` varchar(100), `sex` varchar(100) , `nationality` varchar(100), `post` varchar(100), `zyjslb` varchar(100), `zyjsdj` varchar(100) , `zhixi` varchar(100), `xueli` varchar(100) , `age` int(10) , PRIMARY KEY (`userid`) )
MDX查询语句:select NON EMPTY {[Measures].[人数]} on columns, NON EMPTY {([部门].[全部部门], [职系].[全部职系], [专业技术资格类别].[全部专业技术资格类别], [专业技术资格等级].[全部专业技术资格等级], [学历].[全部学历], [民族].[全部民族], [性别].[全部性别])} ON rows from Person
http://www.biaodianfu.com/ola...
Schema
Schema 定义了一个多维数据库。包含了一个逻辑模型,而这个逻辑模型的目的是为了书写 MDX 语言的查询语句。这个逻辑模型实际上提供了这几个概念:
Cubes: 立方体
Dimensions: 维度
Hierarchies: 层次
Levels: 级别
Members: 成员
而一个schema 文件就是编辑这个 schema 的一个xml 文件。在这个文件中造成逻辑模型和数据库物理模型的对应。
Cube
一个 Cube 是一系列维度 (Dimension) 和度量 (Measure) 的集合区域。在 Cube 中, Dimension 和 Measure 的共同地方就是共用一个事实表。 Cube 中的有如下几个属性:
name: Cube 的名字。
caption: 标题 , 在表示层显示的。
cache: 是否对 Cube 对应的实表用 mondrian 进行存储 , 默认为 true。
enabled: 是布尔型的 , 若是是被激活 ,Cubes 就执行 , 不然就不予理睬,默认为 true。
Cube 里面有一个全局的标签订义了所用的事实表的表名。
Dimension
他是一个层次( Hierarchies )的集合 , 维度通常有其相对应的维度表 . 他的组成是由层次(Hierarchies)而层次(Hierarchies)又是有级别(Level)组成 . 其属性以下:
name: Dimension 的名称。
type: 类型,有两个可选的类型: StandarDimension 和 TimeDimension ,默认为StandardDimension。
caption: 标题 , 在表示层显示的UsagePrefix加前缀 , 消除歧义。
foreignKey: 外键,对应事实表中的一个列,它经过 <Hierarchy> 元素中的主键属性链接起来。
Hierarchy
你必定要指定其中的各类关系,若是没有指定,就默认 Hierarchy 里面装的是来自立方体中的真实表 . 属性以下:
name: Hierarchy 的名称,该值能够为空,为空时表示 Hirearchy 的名字和 Dimension 的名字相同。当一个 Dimension 有多个 Hierarchy时,注意 name 值要惟一。
hasAll: 布尔型的 , 决定是否包含所有的成员 member。
allMemberName: 全部成员的名字 , 也就是总的标题 , 例如: allMemberName= “所有产品”。
allLevelName: 全部级别的名字,它会覆盖其下全部的 Member 的 name 和全部的 Level 的 name 属性的值。
allMemberCaption: 例如 : allMemberCaption= “所有产品”这个是在表示层显示的内容。
PrimaryKey: 经过主键来肯定成员,该主键指的是成员表中的主键,该主键同时要与 Dimension 里设置的 foreignKey 属性对应的字段造成外键对应关系。
primaryKeyTable: 若是成员表不仅一个,而是多个表经过 join 关系造成的,那么就要经过这个属性来指明 join 的这些表中,哪个与Dimension 里设置的foreignKey 属性造成外键关系。经过该属性来指明主表。
caption: 标题 , 在表示层显示的。
defaultMember
memberReaderClass 设定一个成员读取器,默认状况下 Hierarchy 都是从关系型数据库里读取的,若是你的数据不在 RDBMS 里面的话,你能够经过自定义一个member reader 来表现一个 Hierarchy 。
Level
级别 , 他是组成 Hierarchy 的部分。属性不少,而且是 schema 编写的关键,使用它能够构成一个结构树, Level 的前后顺序决定了 Level在这棵树上的的位置,最顶层的 Level 位于树的第一级,依次类推。 Level 的属性以下:
name: 名称
table: 该 Level 要使用的表名
column: 用上面指定的表中某一列做为该 Level 的关键字
nameColumn: 用来显示的时候使用,若是不定义,那么就采用上面的 column 的值来进行显示。
oridinalColumn: 定义该 Level 上的成员的显示顺序,若是不指定,那么采用 column 的值。
parentColumn: 在一个有父 – 子关系的 Hierarchy 当中,当前 Level 引用的是其父成员的列名。比如是一张部门表,在一张表里表现部门的上下级关系,一个是主键,确定还有一个字段为链接到该主键的外键的列名,这里的 parentColumn 指的就是这个列名。
nullParentValue: 若是当前的 Level 是有上下级关系(设置了 parentColumn 属性),若是该 Level 又处于顶级,咱们须要将顶级的数据取出来,这里指的是位于顶级的父成员的值,有些数据库不支持 null, 那么也可使用0或-1 等,这就表示顶级的成员的父 ID 为0 或为-1 。
type: 数据类型,默认值为 string 。固然还能够是 Numeric 、 Integer 、 Boolean 、 Date 等。
uniqueMembers: 该属性用于优化产生的 SQL ,若是你知道这个级别和其父级别交叉后的值或者是维度表中给定的级别全部的值是惟一的,那么就能够设置该值为 true ,不然为 false 。
levelType: 该 Level 的类型,默认为 regular (正常的),若是你在其 Dimension 属性 type 里选择了 TimeDimension 那么这里就能够选择 TimeYears 、 TimeQuarters 、 TimeMonth 、 TimeWeeds 、 TimeDays 。
hideMemberIf: 在何时不隐藏该成员,可选的值有三个: Never 、 IfBlankName 、 IfParentName
approxRowCount: 该属性能够用来提升性能,能够经过指定一个数值以减小判断级别、层次、维度基数的时间,该属性在经过使用 XMLA 链接Mondrian 颇有用处。
caption: 标题 , 在表示层显示的。
captionColumn: 用来显示标题的列。
formatter: 该属性定义了 Member.getCaption() 方法返回的动做值,这里须要是一个实现了 mondrian.olap.MemberFormatter 接口的类,用来对Caption地值进行格式化。
Join
对于一个 Hierarchy 来讲,有两种方式为其指定:一种是直接经过一个 Table 标签指定;一种是经过 Join 将若干张表链接起来指定。一旦采用 Join 的话,那么就要在 Hierarchy 里的 primaryKeyTable 属性指定主表。
Measure
Measure 就是咱们要计算的数值,操做的核心。它的属性以下:
name: 名称。
aggregator: 要采用的计算函数。
column: 要计算的列名。
formatString: 计算结果的显示格式。
visible: 是否可见。
datatype: 数据类型,默认为 Numeric
formatter: 采用类来对该 Measure 的值进行格式,具体参考 Level 的 formatter 属性。
caption: 标题,用来显示时使用。
归纳总结一下:在多维分析中,关注的内容一般被称为度量(Measure),而把限制条件称为维度(Dimension)。多维分析就是对同时知足多种限制条件的全部度量值作汇总统计。包含度量值的表被称为事实表(Fact Table),描述维度具体信息的表被称为维表(Dimension Table),同时有一点须要注意:并非全部的维度都要有维表,对于取值简单的维度,能够直接使用事实表中的一列做为维度展现。
下描述了一个数据库的结构。该数据库中共有五张表,分别是Sales表,Customer表,Time表,Product表和Mfr表。这个数据库的做用是存储每一笔交易:包括这笔交易发生在什么时间,交易的产品类型,进行交易的客户信息,交易方式,交易了多少件产品以及成交金额是多少。
模型中有一张事实表(Sales),两个度量列(units和dollars),四个维度表(Product, Mfr, Customer, Time)。在这个星型模型的最顶层,咱们建立了如下多维模型:
[Sales]立方体包含[Unit sales]和[Dollar sales]两个度量值;
[Product]维度包含[All Products],[Manufacturer],[Brand],[Prodid]四个级别;
[Time]维度包含[All Time],[Year],[Quarter],[Month],[Day]五个级别;
[Customer]维度包含[All Customers],[State],[City],[Custid]四个级别;
[Payment Method]维度包含[All Payment Methods],[Payment Method]两个级别。
假设如今咱们要对交易作一些统计,例如,某一件特定产品在某一个时间段内以某种特定方式总共卖出多少件或多少钱,这时成交产品数和成交金额是咱们最终关注的内容,其余的因素例如时间、产品、方式等都只是对咱们最终关注内容进行统计的限制条件。
在上面的例子中,限制条件有时间、产品类型、用户类型和交易方式,
有时咱们并不须要同时使用全部的限制条件,例如,当咱们只想知道指定产品的成交总金额时,那么除了产品类型以外其余三个限制条件都是多余的,而在查询时,须要在整个事实表中执行查询,找出产品类型为指定类型的全部产品而后再作统计,为了提升查询效率,咱们能够新建一张表,这张表按照产品类型把事实表中的行合并到一块儿,合并的方式是抛弃其余维,把度量值按特定的方式(max,min,sum,count或avg)整合到一块儿。这种表被叫作聚合表(Aggregate Table)。
聚合表的应用场景
事实表中的行构成了一个集合,每一维(或若干维)按照其取值的不一样能够将事实表这个全集划分红若干个不相交的子集。聚合表所作的工做实际上就是把划分出的子集归为数据库表中的一行,这样作一方面能够减小数据库表的行数,另外一方面也省去了查询时所须要作的一些统计工做,从而提升查询时的效率。
使用Mondrian作大数据量(如>100W行)的OLAP分析时,考虑是否可使用聚合表进行优化。
然而Mondrian的优化方式又不限于聚合表这一种,是否要进行聚合表优化,要根据实际状况来决定。
Mondrian目前并不提供对聚合表的数据同步机制,若是要作实时OLAP,须要本身实现聚合表和事实表中的数据同步。
聚合表的定义见:http://www.cnblogs.com/panfen...
http://sourceforge.net/projec...
http://blog.csdn.net/athenaer...
其余参考:http://blog.csdn.net/zhangzho...
http://blog.csdn.net/xiaolang...
http://wushexu.iteye.com/blog...
MDX(Multidimensional Expressions)是多维 数据库(OLAP 数据库)的查询语言.
Mondrian是java中的一个OLAP与MDX解析引擎,它会解析MDX,转换成SQL来查询关系数据库(多是多条查询)。
MDX 的内容不少,功能强大,这里只介绍最基础和最重要的部分。
如下是里两条MDX 查询语句及其查询结果
语句1:
SELECT { [Measures].[Dollar Sales], [Measures].[Unit Sales] } on columns, { [Time].[Q1, 2005], [Time].[Q2, 2005] } on rows FROM [Sales] WHERE ([Customer].[MA])
语句 2
SELECT { [Time].[Q1, 2005], [Time].[Q2, 2005], [Time].[Q3, 2005] } on columns, { [Customer].[MA], [Customer].[CT] } on rows FROM Sales WHERE ( [Measures].[Dollar Sales] )
第一条语句查询对[Customer].[MA]这个客户在 2005 年第1、第二季度的销售额、报表期销售额。
第二条语句查询对[Customer].[MA], [Customer].[CT]这两个客户在 2005 年前三个季度的销售额。
能够看到,mdx 有相似 sql 的结构,一样有 select、from、where 这三部分。但也有不少不一样。
Select 字句指定一个集合,把它放到某个轴上。
From 字句说明要从哪一个数据立方体来查询。
方括号([])用于维度名、层次名、维度成员名,避免名字和函数混淆(函数名
是不加方括号的)。
Where 字句指定切片,即对不出如今轴上的维度的成员的限定。
Mdx 没有 group by 字句。其实分组是隐含的。
Mdx 没有 order by 字句。排序只会对某个轴进行,经过使用排序函数。
和 sql 同样,mdx 也是不区分大小写的,而且能够随意分行。
Mdx 中也能够包含注释,除了支持 sql 的--注释外还支持//和/ ... /注释。
用 on {axis}语法来把维度分配到轴(Axis,复数 Axes)上,一个查询能够有多个轴。
不一样轴用逗号分隔,分配的顺序是不要紧的。但若是把轴调换(如 A on columns, B on rows 改为 A on rows, B on columns),结果的行和列也会转置过来。
轴用 axis(0),axis(1),axis(2)...表示,前五个轴可使用别名 Columns,Rows,Pages,Chapters,Sections。所以 on Columns 等价于 on axis(0)。超过 5 个轴时只能用 axis(5),axis(6)...来表示(极少会须要这么多的轴)。
不少实现(包括 Mondrian)支持仅用数字表示轴,所以 on Columns 能够写成 on 0。axis(0)和别名表示能够混用,例以下面语句是能够的:
SELECT { [Time].[Q1, 2005], [Time].[Q2, 2005] } on axis(0), { [Customer].[MA], [Customer].[CT] } on rows FROM Sales
轴必须从 0 开始,而且连续,不能跳过。下面的是不能够的:
SELECT { [Time].[Q1, 2005], [Time].[Q2, 2005] } on rows, { [Customer].[MA], [Customer].[CT] } on pages FROM Sales
错误,跳过了轴 axis(0)(columns) 。
在大多查询中,轴通常是两个。一个轴也能够,甚至 0 个轴。
若是轴多于两个,就无法在平面上表示。若是维度多于两个,须要把多个维度(交叉后)放到一个轴上。
切片(Slice)维度就是出如今 MDX 语句 WHERE 子句中的维度,跟 SQL 同样,表示对数据集的限制。例如 MDX 语句:
SELECT
{[Product].[All Products].[Food], [Product].[All Products].[Drink]} ON COLUMNS
FROM [Sales]
WHERE [Time].[Year].[2005]
限制了查询的数据范围,只限于 2005 年。语法和 SQL 不同,[Time].[Year].[2005](是一个元组)自己就表示了一个条件。这能够当作对数据立方体从某个方向进行切片(从 Time维度的方向)获得一个子立方体,所以叫切片。
切片维度不会出如今轴上。上面的时间维度不会出如今轴上。
一个维度不能同时出如今轴维度(SELECT 的维度)和切片维度上。
切片器维度只可接受评估为单个元组的表示式
若是一个维度既没有出如今轴维度上,也没有出如今切片维度上,就会用维度的(默认层次的)默认成员进行切片。通常维度的默认成员是“All xxx” ,所以默认是对这个维度全部成员的数据进行汇集操做。例如:
SELECT {[Time].[Year].Members } ON COLUMNS
FROM [Sales]
Product 维度没有出如今轴维度和切片维度上。若是 Product 的默认成员是[All Products],就会查询全部产品的销售额汇总,符合人的习惯。上面语句至关于:
SELECT {[Time].[Year].Members } ON COLUMNS
FROM [Sales]
WHERE [Product].[ All Products]
维度有一个函数 defaultMember 能够返回维度的默认成员,所以也至关于:
SELECT {[Time].[Year].Members } ON COLUMNS
FROM [Sales]
WHERE [Product]. defaultMember
除了 Product 维度,其余没有出如今轴维度和切片维度上的维度也是同样的。
度量维度(为了一致能够把度量当作一个维度:Measures 维度)是没有”All xxx”成员的,它的默认成员能够明确设置,若是没设置,就是第一个度量。若是默认度量是[Store Sales],
下面的查询
SELECT {[Time].[Year].Members } ON COLUMNS
FROM [Sales]
和
SELECT {[Time].[Year].Members } ON COLUMNS
FROM [Sales]
WHERE [Measures]. [Store Sales]
是等价的。
一个维度的默认成员、是否有 All 成员(通常都应该有),是能够在 Schema 文件中设置的。
若是没有明确设置默认成员,默认成员就是 All 成员,若是没有 All 成员,默认成员就是第一个成员。
元组和集合是 MDX 中的两种数据类型,也是 MDX 语句的构件。
元组(Tuple)就是一个或多个维度的成员的组合当一个元组有多个维度时,必须用括号括起来
([Customer].[Chicago, IL], [Time].[Jan, 2005])
一个元组能够表明立方体的一个切片
以这种语法构造的元组能够直接用于
SELECT
{ ( [Time].[2005], [Measures].[Dollar Sales],
( [Time].[Feb, 2005],[Measures].[Unit Sales] )
} ON COLUMNS ,
{ [Product].[Tools], [Product].[Toys]} ON ROWS
FROM [Sales]
元组不能嵌套
元组用于定义来自多维数据切片;他是由一个或多个维度的单个成员的有序集合组成。元组内不包含来自同一个维度的多个成员(能够理解为坐标),元组用()包围。
where 字句也是一个元组,用以指定一个数据切片
集合(Set)是零个、一个或多个元组的有序集合。不像数学上的集合,MDX 集合一个元组能够出现屡次,并且顺序是重要的。
集合最经常使用于在Mdx查询中定义轴维度和切片器维度, 一般的指定集合的方式是把一个元组列表用花括号括起来。如{ [Customer].[MA],
[Customer].[CT] }就表示一个集合,集合里是客户维度的两个成员。一个集合中的全部元组必须有一样的维度性质,即所表示的维度及其顺序。
使用下面的集合将会报错,由于维度的顺序不同:
{ ( [Time].[2005], [Measures].[Dollar Sales] ), ( [Measures].[Unit Sales], [Time].[Feb, 2005] ) }
不少函数均可以返回一个集合
要把维度成员放在轴上,能够列举维度的成员,例如{ [Customer].[MA], [Customer].[CT] }。也能够经过范围语法或一个函数获得成员的集合。
经过坐标值能够定义出每一个成员的名称
冒号(:)语法能够表示成员范围。冒号先后是同一个层次的起点和终点两个成员。
SELECT
{ [Time].[2003] : [Time].[2008] } on columns,
{ [Product].[Drinks] : [Product].[Bread] } on rows
FROM [Sales]
时间维度表示 2003 年到 2008 年(6 个成员),产品维度表示从 Drinks 到 Bread。这一般跟排序方式有关。
集合里能够包含子集合。例以下面集合,包含 2001 年的前三个月跟后三个月。
{ { [Time].[January-2001] : [Time].[March-2001] } ,{ [Time].[October-2001] : [Time].[December-2001] } }
能够用成员名称或成员键引用某个成员。
&符号能够标记出其父级中的元素集合中的值也叫作元素值,&符号用于区分红员键和成员名称。例如:
SELECT {[Dim Region].[City].&[上海],[Dim Region].[City].&[北京]} ON COLUMNS, {[Dim Time].[Day Of Month].&[13],[Dim Time].[Day OfMonth].&[14]} ON ROWS FROM [MKAS] WHERE ([Measures].[Fact Ind Count])
大多时候须要获得一个维度、层次、层的所有成员,这个时候可使用.Members 操做(函数)。好比[Time].[Years].Members 能够获得全部年份。
SELECT
{ [Time].[Years].Members} ON COLUMNS,
{ [Product].[Line].Members} ON ROWS
FROM [SteelWheelsSales]
WHERE [Measures].[sales]
这个语句查询全部年份、全部产品线的销售额,把年份放在列上,产品线放在行上。
有时候须要获得某个成员的下一层次的所有成员,这是须要用.Children 函数。这在下钻操做时常常用到。
例如要获得产品线 Classic Cars 下的全部产品,能够这样[Product].[Line].[Classic
Cars].Children。[Product].[Line].[Classic Cars]是 Product 维度 Line 层的一个成员。
.Children 只能获得直接下级成员,若是须要多级,须要使用 Descendants()函数。语法是:
Descendants (member [, [ level ] [, flag]] )
Descendants 返回 member 成员下 level 层的成员,可选标志 flag 有多个选项,以设置包含最下一层上面的哪些层的成员。
如下是一个例子,查询 Tools 和 Toys 两类产品在 2005 年各月的销售额,由于年和月两个层次中间有一个季度层次,因此不能用[Time].[2005].Children。
SELECT
{ [Product].[Tools], [Product].[Toys] } ON COLUMNS,
Descendants ([Time].[2005],[Time].[Month],SELF_AND_BEFORE) ON ROWS
FROM Sales
WHERE [Measures].[Dollar Sales]
flag 设为 SELF_AND_BEFORE,能够看到行上包含了 2005 年和各个季度(若是设为SELF 则不会包含) 。
有时要获取维度成员的属性(维表上的某些列),这时可使用 dimemsion properties子句。dimemsion关键字能够省略。
如下查询同时获取客户所在地的邮编属性
SELECT
{ [Customer].[Akron, OH].Children }
DIMENSION PROPERTIES [Customer].[Zip Code]
on columns,
{ [Product].[Category].Members } on rows
FROM Sales
WHERE ([Measures].[Units Sold], [Time].[July 3, 2005])
在多维空间,数据不少时候是稀疏的。好比:好比,不是每个产品都销售给了全部的客户,不是每个客户在每一个时期都购买了产品。若是按维度全部成员交叉得出报表,就会有不少空行、空列。
要从查询结果去掉这些空行
SELECT
{ [Time].[Jan,2005],[Time].[Feb,2005] } ON COLUMNS ,
NON EMPTY { [Product].[Toys], [Product].[Toys].Children } ON ROWS
FROM Sales
WHERE ([Measures].[Dollar Sales], [Customer].[TX])
这样空行就去掉了。non empty 可用于任何轴上。
不少时候,咱们须要对两个不一样的集合进行交叉,也就是要获得两个集合成员的全部组合。CrossJoin()函数就是用来获得组合的最直接方式,它的语法是 CrossJoin (set1, set2)
如下语句在每一个季度下分出两个度量
SELECT
CrossJoin (
{ [Time].[Q1, 2005], [Time].[Q2, 2005]},
{ [Measures].[Dollar Sales], [Measures].[Unit Sales] }
) ON COLUMNS,
{ [Product].[Tools], [Product].[Toys] } ON ROWS
FROM Sales
CrossJoin 的结果是一个集合。所以支持CrossJoin 嵌套。
Filter 函数用来筛选一个集合,它以一个集合和一个 boolean 表达式为参数
Filter (set,boolean-expression)。
例如,如下表达式会返回关联的产品销售额至少为500 的产品分类的集合。
Filter (
{ [Product].[Product Category].Members },
[Measures].[Dollar Sales] >= 500
)
要求销售额至少为 150 而且销售额要至少在成本的1.2 倍以上
Filter (
{ [Product].[Product Category].Members },
([Measures].[Dollar Sales] >= 1.2 *[Measures].[Dollar Costs])
AND [Measures].[Dollar Sales] >= 150
)
Order()函数用于对一个集合进行排序,语法:
Order (set1, expression[,ASC| DESC | BASC | BDESC])
SELECT
{ [Measures].[Dollar Sales] } on columns,
Order (
[Product].[Product Category].Members,
[Measures].[Dollar Sales],
BDESC
) on rows
FROM [Sales]
WHERE [Time].[2004]
在 sql 中能够增长计算出来的列,MDX 中一样也能够,在 MDX 中叫计算成员(CalculatedMember)。由于MDX 操做的是多维数据,计算成员实际是给一个维度增长成员。
语法:
with
member 成员标识 as ‘表达式’ [, 属性...]
select ...
表达式用单引号引注。
如下例子增长一个新的度量[Avg Sales Price]
WITH
MEMBER [Measures].[Avg Sales Price] AS
'[Measures].[Dollar Sales] / [Measures].[Unit Sales]'
SELECT
{ [Measures].[Dollar Sales], [Measures].[Unit Sales],
[Measures].[Avg Sales Price]
} on columns,
{ [Time].[Q1, 2005], [Time].[Q2, 2005] } on rows
FROM Sales
WHERE ([Customer].[MA])
当不止一个维度增长了计算成员时,因为每一个维度的成员都有计算公式,在这些维度的交叉点上,就能够有多种计算顺序。这时候就不须要考虑公式优先级的问题。所以引入了 SOLVE_ORDER 属性
WITH
MEMBER [Measures].[Avg Sales Price] AS
‘[Measures].[Dollar Sales] / [Measures].[Unit Sales]',
SOLVE_ORDER=0
MEMBER [Time].[Q1 to Q2 Growth] AS
‘[Time].[Q2, 2005]- [Time].[Q1, 2005]’,
SOLVE_ORDER=1
SELECT
{ [Measures].[Dollar Sales], [Measures].[Unit Sales],
[Measures].[Avg Sales Price]
} on columns,
{ [Time].[Q1, 2005], [Time].[Q2, 2005], [Time].[Q1 to Q2 Growth] } on rows
FROM [Sales]
WHERE ([Customer].[MA])
命名集合(Named Set)容许预先定义的一个集合,供后面的语句使用。语法和计算成员相似。
with
set 集合标识 as ‘集合表达式’
select ...
WITH
SET [User Selection] AS ‘{ [Product].[Action Figures], [Product].[Dolls] }'
MEMBER [Product].[UserTotal] AS ‘Sum ( [User Selection] )’
SELECT
{ [Time].[Jan, 2005], [Time].[Feb, 2005] } ON COLUMNS,
{ [Product].[Toys], [User Selection], [Product].[UserTotal] } ON ROWS
FROM Sales
WHERE ([Measures].[Unit Sales])
http://mondrian.pentaho.com/d...
列出一些重要的,按返回类型来分类。
.currentMember
.parent
.prevMember/.nextMember
.firstChild/.lastChild
.firstSibling/.lastSibling
Ancestor(<Member>, <Level>)
Ancestor(<Member>, <Numeric Expression>)
LAG 返回当前成员开始往前数的本层的第几个成员.
<Member>.Lag(n)
n是索引,0 是它自己,1是前一个(.prevMember)
LEAD 相似 Lag(),但方向相反
OpeningPeriod 返回某个层次上第一个后代成员
语法:OpeningPeriod([<Level>[, <Member>]])。
ClosingPeriod 返回某个层次上最后一个后代成员
PARALLELPERIOD 返回一个成员同层次对应位置的成员
ParallelPeriod([<Level>[, <n>[, <Member>]]])在时间维度上取同期(如上年同期)等的时候须要用到它。
前面介绍的 members、children、descendants、crossJoin、filter、order 都是集合函数
union
合并两个集合。语法:Union(set1,set2[, ALL]) All 标志指示保留重复元素
Except
从set1里去除set2的元素,即求两个集合的差。Except(set1,set2[, ALL])
Head/Tail
返回集合Head/Tail元素 。 Head/Tail(set[, <count>))。
.SIBLINGS
返回成员的兄弟成员,包括它本身。<Member>.Siblings。
.MEMBERS
返回维度/层次的成员。<Dimemsion>.Members
DESCENDANTS
返回成员的后代成员。Descendants (member, [level[,flag]])
flag 能够是:SELF、BEFORE、SELF_BEFORE_AFTER、LEAVES、AFTER、SELF_AND_BEFORE、SELF_AND_AFTER。
DrillDownLevel(set,[level])
下钻(一级)成员。
DrillDownLevelBottom(set,index,level)
下钻最下一级成员。
DrillDownLevelBTop(set,index,level)
下钻最上一级成员。
DrillDownMember
下钻集合2中的成员.DrillDownMember(set1,set2[,Recursive])
TopCount 返回前n个数据的集合
<Set> TopCount(<Set>, <Numeric Expression>, <Numeric Expression>) <Set> TopCount(<Set>, <Numeric Expression>)
(TopCount, BottomCount, TopPercent, Hierarchize ,etc.)
count (set [,INCLUDEEMPTY])
可选标记指定是包含无数据的元组
Sum (set [,数值表达式]])
max/min/median/avg(set [,数值表达式]])
IS
object is object2。
例如:
[Jan 2000].PrevMember IS NULL
[Jan 2000].Level IS [Time].[Month]
ISEMPTY
判断一个值是否为空。语法:IsEmpey(表达式)。
NAME
返回维度、层次等的名称。语法:<Dimension/Hierarchy/Level/Member>.Name
PROPERTIES
返回成员的属性值。语法:<Member>.properties(<属性名>)
这里是一些返回类型不定的函数。iiF根据条件返回值,相似Excel 的If 函数。语法:iif(<布尔表达式>, <值1>, <值2>)。ITEM根据索引返回集合中元素。语法:item(set, <index>)。返回类型通常为元组。