mondrian 如何使用xml存储olap服务器的元数据

Mondrian是一个开放源代码的Rolap服务器,使用java开发的。它实现了xmla和jolap规范,而且自定义了一种使用mdx语言的客户端接口。Mondrian是olap服务器,而不是数据仓库服务器,因此Mondrian的元数据主要包括olap建模的元数据,不包括从外部数据源到数据库转换的元数据。也就是说Mondria的元数据仅仅包括了多维逻辑模型,从关系型数据库到多维逻辑模型的映射,存取权限等信息。在功能上,Mondrian支持共享维和成员计算,支持星型模型和雪花模型的功能。
Mondrian中使用物理的xml文件存储元数据,它的设计者规定了xml文件的格式。下面简单介绍一下它是如何存储元数据的。

一个模式定义一个多维数据库,它包括一个逻辑模型,由立方体,层次,成员和逻辑模型到物理模型的映射构成。一个逻辑模型由可以用MDX语言来查询。Mondrain的模型由xml文件来描述。现在创建模式的唯一途径是用文本编辑a器编辑xml文件。Xml的语法不是太复杂,因此没有想象中的那么难。目前正在开发一个图形界面的程序来创建和修改模式。
一个模式最重要的组成部分是立方体,度量和维:在一个主题域中立方体是维和度量的集合。一个度量是一个可测量的数值,比如产品销售的数量或者详细清单的价格
一个维是一个属性或者是属性的集合, 通过维你可以将度量划分到字类中。比如:你希望将销售产品按颜色,顾客性别,售出的商店分为八个部分,那么颜色,性别,商店都是维。

这个模型包含了一个销售cube,这个cube有两个维,时间和性别维;两个度量,销售数量和销售总额。
我们可以在这个模型上写一个 MDX 查询:
select {[Measures].[Unit Sales], [Measures].[Store Sales]} on columns,
{[Time].[1997].[Q1].descendants} on rows
from [Sales]
where [Gender].[F]
这 个查询涉及到了销售立方体, 每一个维 [Measures], [Time], [Gender], 这些维的多个成员.

下面详细地介绍一下模式定义:
一个立方体是一个或者多个维和度量的集合,通常是一个事实表,这里是 ‘sales_fact_1997". 事实表保存了需要计算的列和包含维的参考表.

这里用  元素定义事实表. 如果事实表 不在默认的模式中, 你可以用"schema"属性指定一个明确地模式,例如:

你也可以利用 和 结构来创建更复杂的sql .
度量
销售立方体定义了两个维 "Unit Sales" 和 "Store Sales".
aggregator="sum" formatString="#,###"/>
aggregator="sum" formatString="#,###.00"/>
每个度量有一个名字,对应事实表中的一列, 采用一个聚集函数 (usually "sum").
一个可选的格式字符串指定了值如何被打印. 这里我们选择销售数量不带小数的输出(因为销售数量是整数) ,销售总额带2位小数 . 符号',' 和 '.' 是对地区敏感的, 因此如果是在意大利运行, 销售总额可能会出现 "48.123,45". 你可以用 advanced format strings来实现更严格的效果.度量值不是从列中来的,而是从立方体的单元中来的

性别维由单一的层次组成,仅有一层。

对于任意给定的销售, 性别维是指购买改产品的客户的性别. 它通过连接事实表"sales_fact_1997.customer_id"和维表"customer.customer_id"
来表示 。"gender" 包括两个值, 'F' 和 'M', 因此性别维包含的成员: [Gender].[F] and [Gender].[M]. 因为 hasAll="true", 系统产生一个特别的 'all' 层, 仅包括一个成员 [All Genders].

第一个层次没有指定名称.缺省的情况下,一个层次拥有和它的维相同的名称。,因此第一个层次成为"Time".这些层次没有太多的共同之处,他们甚至没有相同的表,除非它们连接了实施表中的同一列"time_id"。在一个维上存在两个层次的原因是这样对最终用户是有用的. 如果一个维上存在两个层次, MDX会强制不允许在一个查询中同时用到他们.
A dimension can live in the fact table:

每个维包含有多层组成的一个层次,

大多数维都是仅有一个层次,但有时候一个维有多个层次。比如:你可能希望在时间维上从天聚集到月,季度和年;或者从天聚集到周和年。这两种层次都是从天到年,但是聚集的路径不同。大多数层次有全成员,全成员包括层次的所有成员,因此能够代表他们的总合。它通常命名为'All something',比如:'All stores'.

星型模式和雪花模式
mondrian支持星型模式和雪花模式。下面介绍一下雪花模式的建模,它需要用到操作符 .

这里定义一个 "Product" 维 由三个表构成. 事实表连接 表"product" (通过外键 "product_id"),表"product"连接表"product_class" (通过外键 "product_class_id"),表"product_class"连接表 "product_type" (通过外键 "product_type_id"). 我们利用 元素的循环嵌套, 带有两个操作对象; 操作对象可能是表,连接或者查询 。
按照操作对象行的数目来安排次序,表 "product" 的行数最大, 因此它首先出现连接事实表;然后是表 "product_class"和 "product_type",在雪花的末端拥有的行数最小.
注意外部元素 有一个属性 rightAlias. 这是必要的,因为join 的右边(是内部元素 ) 有可能是许多表组成的.这种情况下不需要属性leftAlias,因为列 leftKey 很明确的来自表 "product".

共享维
当为一个连接生成SQL的时候, mondrian 需要知道连接哪一个列. 如果一正在连接一个多表连接, 你需要告诉它连接这些表里的哪一个表,哪一个列.
因为共享维不属于一个cube,你必须给它们一个明确的表 (或者数据源). 当你在一个特别的cube里用他们的时候, 你要指定外键 foreign key. 下面的例子显示了 Store Type 维被 连接到 Sales cube ,用了外键 sales_fact_1997.store_id, 并且被连接到Warehouse cube ,用了外键 warehouse.warehouse_store_id

虚拟 cubes
父子层次
一个使用方便的层次 有一个严格的层的集合, 成员与层紧密的联系.比如,在 Product 层次中, 任何产品名称层的成员在商标层上都有一个父亲 ,商标层上的成员在产品子目录层也都有一个父亲. 这种结构对于现实世界中的数据有时候太严格了.
一个父子层次只有一层 (不计算 'all' 层), 但是任何成员可以在同一层上有父亲成员. 一个典型的例子是Employees 层次

这里parentColumn 和nullParentValue是重要的属性:
属性parentColumn 是一个成员连接到它父亲成员的列名。在这种情况下, 它是指向雇员经理的外键。元素的子元素 是与属性 parentColumn 有相同作用的,但是元素允许定义任意的SQL表达式, 就像元素 . 属性 parentColumn (或者 元素) 是维一向Mondrian指出 层次有父子结构的。
属性 nullParentValue 是指明成员没有父成员的值 。 缺省情况下 nullParentValue="null", 但是因为许多数据库不支持null, 建模时 用其他值来代替空值,0和-1.

物理结构
member reade
member reader 是访问成员的方法. 层次通常以维表为基础建立的 , 因此要用sql来构造.但是甚至你的数据没有存在于 RDBMS, 你可以通过一个 Java 类来访问层次。(自定义 member reader)
Here are a couple of examples:
DateSource (to be written)生成一个时间层次. 按常规,数据仓库工具生成一个表 ,每天包含一行。但是问题是这个表需要装载,并且随着时间的变化能够添加更多的行。 DateSource 在内存中按照要求生成日期成员.
FileSystemSource (to be written) 按照目录和文件的层次描述文件系统。 Like the time hierarchy created by DateSource, this is a virtual hierarchy: the member for a particular file is only created when, and if, that file's parent directory is expanded.
ExpressionMemberReader (to be written) 创建了一个基于表达式的层次。
自定义member reader 必须实现接口 mondrian.rolap.MemberSource. 如果你需要实现一个更大的成员操作集合, 需要实现接口 interface mondrian.rolap.MemberReader; 否则, Mondrian在 mondrian.rolap.CacheMemberReader中封装 你的 reader类.你的 member reader 必须有一个公共的构造函数,这个构造函数拥有参数(Hierarchy,Properties),抛出未检查的错误.
Member readers 用 元素 的属性memberReaderClass来声明; 任何 子元素通过属性构造函数来传递.
类 "com.foo.MyCellReader" 实现了接口interface mondrian.olap.CellReader.

存取控制
可以定义存取控制的属性(角色), 作为模式的一部分, 并且可以在建立连接的时候设置角色。
定义角色
角色可以通过 元素来设置 , 它是元素 的直接的子元素.

元素 定义了模式中缺省的对象方问权限. 访问属性可以是 "all" 或者 "none"; 这个属性可以被具体的权限对象继承. 在这个例子中, 因为 access="none", 用户只能浏览"Sales" 立方体, 这里明确的赋予了这个权限.
元素 定义了立方体的访问权限. 就像 , 属性access 可以是"all" 或者 "none", 并且能够被cube中具体的子对象继承.
元素 定义了层次的访问权限. 属性access 可以是"all", 意思是所有的members都是可见的; "none",意思是 hierarchy的存在对用户是隐藏的; "custom", 你可以利用属性 topLevel 定义可见的最高层 (阻止用户 进行上卷操作, 比如浏览税收 上卷到 Store Country 层); 或者用属性 bottomLevel?? 定义可见的最底层 (这里阻止用户查看顾客个人的细节数据);或者控制用户查看哪一个成员集合,通过嵌套定义元素 .
你也可以只定义元素 ,如果模式的 有属性access="custom". Member grants 赋予 (或者取消) 访问给定的成员, 以及它的所有子成员.










你可能感兴趣的:(设计模式,数据结构,sql,xml,浏览器)