从前到现在,用户需要从IT系统中获取信息的变化无常与程序员从传统数据库中制作报表的代价是一个永恒的矛盾。
这边厢程序员为了应付客户忽然而至的报表需求痛苦不已, 客户只想要他想知道的东西,不会管查询语句有多么复杂,优化从海量数据中提取报表的速度有多么困难。
那边厢客户为了等程序员做一个报表,快则半天,慢则一周,事情都过去了。明明只想知道一样很简单的东西, 程序员却要抱怨查询是多么复杂,数据结构是如何制约。有时候出一个报表要呆在屏幕前等半天。
而OLAP是唯一一种真正让用户获得自己所需要的报表而且不用付出巨大实现代价的方法。它能够让用户自由的定制自己的查询条件,观察、累计的维度,最后从海量数据中快速生成它。
方案经过几年的发展,各大数据库供应商都有了自己的OLAP方案。不过我们一来不想把产品绑定在某个数据库上,二来没钱,所以还是要寻求穷人们自己的免费且底层数据库通用的方案。
从AgileJava的Blog上,看到了Mondrian + JPivot:
Mondrian蒙德里安,OLAP核心引擎,负责从关系数据库中计算、缓存数据,响应来自表现层的使用MS家 MDX语法的查询。这个微软家的MDX语法,学起来并不难,SQL Server的书也统统有教。
在这一层要做的事情就是定义一个schema元模型,包括 维度(Dimensions), 层次(Hierarchies),级别(Levels),和成员(Members)等。Mondrian要根据它来从关系数据库中聚合数据响应MDX语法的查询。
JPivot
OLAP JSP custom tag library。提供OLAP Navigator与多 维数据的显示,并支持图表生成和Export to Excel。Mondrian的御用表现层。
初遇
Mondrian用了MS家著名的FoodMart数据作例子,Access作底层数据库,JPivot做表现层,让你几分钟之内就能把Example跑起来,感受一下OLAP报表是什么样子的。跑完一遍之后,我就发现做个客户自定制的OLAP报表如此简单.....
如前所说,Mondrian是OLAP的核心引擎,负责从关系数据库中计算、缓存数据,响应来自表现层的使用MS家 MDX语法的查询。具体表现形式呢,就是一个jar,随Tomcat启动。
看完那个FoodMart的Sample之后, 该自己动手了。
首先第一步是设计OLAP的数据库结构。
因为和业务数据库相比,OLAP需要冗余一些数据达到更快的查询。
设计前可以先参拜一下那本经典的《完全维度设计指南》,中文版的几下就能翻个大概。
其实说白了就是去除与报表无关的列,把订单、订单明细两个表合并成一个销售事实表,把产品,产品分类两个表合并成一个产品维表这几个动作。
设计完之后,应该会有几个装有统计数据和维表外键的事实表,和几个用于分类,排序,过滤的维表。
第二步是把业务数据库里的数据导过来。
有不少ETL的工具,弄出一大堆映射文件,转换类来。不过我还是喜欢直接写SQL快捷,可能我面对的不是一天一个G的数据库吧。
第三步是把刚才设计的数据库结构定义成Schema
schema元模型包括 维度(Dimensions)、层次(Hierarchies)、级别(Levels)、和成员(Members)等。Mondrian要根据它来从关系数据库中聚合数据响应MDX语法的查询。
在这一步之前记得先装一个中文版的SQL Server2000,里面的Help文件有详细的解释。
另外jprovit有一个子项目,是这个schema的Eclipse Plug-in。即使不用这个Plug-in,有了它的DTD,在其他XML编辑器里也能避免拼写错误引起的冤枉时间。
用Sample中的FoodMart.xml做蓝本,两下就能Copy Paste出自己的schema来。
最后,注意Oracle的列名必须全大写。
JPivot 是Mondrian的表现层TagLib,一直保持着良好的开发进度。
已经好久没有用了,趁彻底忘记以前,把小小的心得记下来。
1.汉化
1.1 查找所有resources.properties文件,汉化为resources_zh.properties文件
1.2 native2ascii resources_zh.properties resources_zh.properties
1.3 查找WEB-INF/jpivot下的所有xml文件,汉化为xxx_zh.xml
2.架构
JPivot的架构看似另类,但其实都是精明的选择。
2.1 使用XML/ XSLT渲染OLAP报表
JPivot 使用 WCF (Web Component Framework) ,基于XML/XSLT来渲染Web UI组件。这使它显得十分另类。不过,OLAP报表这种非常复杂但又有规律可循的东西,最适合使用XSLT来渲染。虽然程序员和编辑器都很不喜欢这种Martin Flower口中有点LISP形式的语言,但Transform Engine这时候的确能比Template Engine(Velocity,Freemarker)更高效的处理OLAP报表及其导航系统的显示。
2.2 完全基于JSP+TagLib
JPivot另外一个可能使人不惯的地方是它完全基于taglib而不是大家熟悉的MVC模式。但如果不基于tabLib,基于任何MVC框架都会使其失去通用性,担不起Mondrain唯一表现层的重任,而且,MVC其实不一定需要那些框架(后述)
2.3 典型的流程及模式:
打开JPivot自带的sample,查看index.jsp文件,典型的流程如下:
1,用户发出 testPage.jsp?query=modrain的请求
2,testPage.jsp上的<wcf:include>根据query参数,匹配/WEB-INF/query/下的modrain.jsp来获取数据
3,modrain.jsp上的<jp:mondrianQuery id="query01">查询数据,放入到query01变量中
4,testPage.jsp上的<jp:table id="table01" query="#{query01}"/>根据query01的结果(领域数据) 准备显示OLAP表格所需的数据(显示数据)
5,testPage.jsp上的<wcf:render ref="table01" xslUri="/WEB-INF/jpivot/table/mdxtable.xsl"/>根据table01的结果,使用xsl,渲染出OLAP表格。
6,循环第4,5步,使用<jp:navigator>等tag准备navigator,chart的数据然后用<wcf>渲染出图表和导航系统.
整个流程,第2步的testPage充当Controller调用第3步的Model层,然后第4,5步 执行Martin Flower讲的Transform Engine两步渲染模式----先从领域数据(比如一些java bean)中转换出格式整齐的,需要显示的数据(比如一段xml),再用xsl将其渲染为最终的表现形式。