http://blog.csdn.net/qzp1991/article/details/44016959
理论准备工作:
一. OLAP
1.什么是OLAP
OLAP(On-LineAnalysis Processing)在线分析处理是一种共享多维信息的快速分析技术;OLAP利用多维数据库技术使用户从不同角度观察数据;OLAP用于支持复杂的分析操作,侧重于对管理人员的决策支持,可以满足分析人员快速、灵活地进行大数据复量的复杂查询的要求,并且以一种直观、易懂的形式呈现查询结果,辅助决策。
2.相关概念
(1)维
是人们观察数据的特定角度,是考虑问题时的一类属性集合构成一个维(如时间维、地理维等)。
(2)级别(Level)
人们观察数据的某个特定角度(即某个维)还可以存在细节程度不同的各个描述方面(如时间维:日期、月份、季度、年)。即维的级别。
(3)成员(Member)
维的一个取值,是数据项在某维中位置的描述。(“某年某月某日”是在时间维上位置的描述)。
(4)度量(Measure)
多维数组的取值,如“某年某月某日的工资”。
(5)钻取(Drill-up和Drill-down)
改变维的层次,变化分析的粒度。Drill-up是将低层次的数据概括到高层次的汇总数据或者说是减少维度;drill-up则是相反,是将汇总的数据深入到细节,或说是增加新维。
(6)切片和切面
是在一部分维上选定值后,关心度量数据在剩余维上的分布。如果剩余的维只有两个,则是切片;如果有三个或以上,则是切块。
(7)旋转
是变换维的方向,即在表格中重新安排维的放置(例如行列互换)
(8)星型模式
由事实表和维表组成,事实表包括所有分析维度的外键和一个度量,维表对应于各个分析的角度,它除了主键以外还包含描述和分类信息。
(9)雪花模式
有时候,维表的定义会变得复杂,例如对产品维,既要按产品种类进行划分,对某些特殊商品,又要另外进行品牌划分,商品品牌和产品种类划分方法并不一样。因此,单张维表不是理想的解决方案,可以采用以下方式,这种数据模型称为雪花模型。
二. Mondrian的学习
2.1 Mondrian的架构
1) 底层数据库
2) 存储层 数据库部分(数据仓库)的建立
将原有的底层数据库转化为一个星型模型或雪花模型的过程
3) 维度层 schema文件 (关键部分)
将存储层的数据仓库转化为一个schema文件,通过schema-workbench或者手写完成,至此就可以通过MDX来对多维数据库进行访问。
4) 展示层 编写jsp文件用于展示 它位于展示层由Jpivot提供展示
JPivot 是Mondrian的表现层TagLib,
Jpivot完全基于JSP+TagLib;
JPivot另外一个可能使人不惯的地方是它完全基于taglib而不是大家熟悉的MVC模式。
但它可以很方便的将多维数据展示给最终用户。
下面是官网提供的Mondrian体系架构图,可以清晰的看出整个项目由底层数据库,存储层的数据仓库,维度层的schema文件和展示层组成。
Mondrian 为客户端提供一个用于查询的API
因为到目前为止,并没有一个通用的用于OLAP查询的API,因此Mondrian提供了它私有的API.
尽管如此,一个常使用JDBC的人将同样发现它很熟悉.不同之处仅在于它使用的是MDX查询语言,而非SQL
下面的java片段展示了如何连接到Mondrian,然后执行一个查询,最后打印结果
- importmondrian.olap.*;
- import java.io.PrintWriter;
-
- Connectionconnection = DriverManager.getConnection("Provider=mondrian;"
- +"Jdbc=jdbc:odbc:MondrianFoodMart;"+"Catalog=/WEB-INF/FoodMart.xml;",null,false);
- Query query =connection.parseQuery("SELECT {[Measures].[Unit Sales], [Measures].[StoreSales]} on columns," +" {[Product].children} on rows "
- +"FROM[Sales] " +"WHERE ([Time].[1997].[Q1], [Store].[CA].[SanFrancisco])");
-
- Result result =connection.execute(query);
- result.print(newPrintWriter(System.out));
与JDBC类似,一个Connection由DriverManager创建,Query对象类似于JDBC的Statement,它通过传递一个MDX语句来创建.Result对象类似于JDBC的ResultSet,只不过它里面保存的是多维数据。
您可以通过查看Mondrian帮助文档里的javadoc来获取更多关于Mondrian API的资料
2.2准备开发工具及环境
本测试需要的环境:
操作系统:Windows 7;
Web服务器:tomcat6.0;
关系数据库:mysql;
开发工具:myeclipse;
相关驱动:mysql-connector-java-3.1.12-bin.jar
(1) 配置jdk和tomcat环境变量
(2) 建立底层数据库
- /*
-
- NavicatMySQL Data Transfer
-
-
-
- SourceServer : localhost_3306
-
- SourceServer Version : 50096
-
- SourceHost : localhost:3306
-
- SourceDatabase : accessinfo
-
-
-
- TargetServer Type : MYSQL
-
- TargetServer Version : 50096
-
- FileEncoding : 65001
-
-
-
- Date:2015-03-02 11:36:40
-
- */
-
-
-
- SETFOREIGN_KEY_CHECKS=0;
-
-
-
-
-
-
-
-
-
- DROPTABLE IF EXISTS `dim_ip`;
-
- CREATETABLE `dim_ip` (
-
- `id` smallint(6) NOT NULL auto_increment,
-
- `dip` varchar(255) default NULL,
-
- PRIMARY KEY (`id`)
-
- )ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
-
-
-
-
-
-
-
-
-
- INSERTINTO `dim_ip` VALUES ('1', '61.183.248.218');
-
- INSERTINTO `dim_ip` VALUES ('2', '61.144.207.115');
-
-
-
-
-
-
-
-
-
- DROPTABLE IF EXISTS `dim_site`;
-
- CREATETABLE `dim_site` (
-
- `id` smallint(6) NOT NULL auto_increment,
-
- `dSiteID` int(11) default NULL,
-
- PRIMARY KEY (`id`)
-
- )ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
-
-
-
-
-
-
-
-
-
- INSERTINTO `dim_site` VALUES ('1', '542');
-
- INSERTINTO `dim_site` VALUES ('2', '548');
-
- INSERTINTO `dim_site` VALUES ('3', '543');
-
- INSERTINTO `dim_site` VALUES ('4', '552');
-
- INSERTINTO `dim_site` VALUES ('5', '551');
-
- INSERTINTO `dim_site` VALUES ('6', '549');
-
-
-
-
-
-
-
-
-
- DROPTABLE IF EXISTS `dim_time`;
-
- CREATETABLE `dim_time` (
-
- `id` smallint(6) NOT NULL auto_increment,
-
- `signinTime` varchar(10) NOT NULL default '',
-
- PRIMARY KEY (`id`)
-
- )ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
-
-
-
-
-
-
-
-
-
- INSERTINTO `dim_time` VALUES ('1', '2015-3-1');
-
- INSERTINTO `dim_time` VALUES ('2', '2015-2-28');
-
- INSERTINTO `dim_time` VALUES ('3', '2015-2-17');
-
- INSERTINTO `dim_time` VALUES ('4', '2015-2-19');
-
- INSERTINTO `dim_time` VALUES ('5', '2015-2-11');
-
-
-
-
-
-
-
-
-
- DROPTABLE IF EXISTS `fact_logs`;
-
- CREATETABLE `fact_logs` (
-
- `fID` varchar(20) NOT NULL default '',
-
- `fSiteID` varchar(20) default NULL,
-
- `fTime` varchar(10) default NULL,
-
- `fIP` varchar(20) default NULL,
-
- `fCount` int(11) default NULL,
-
- PRIMARY KEY (`fID`)
-
- )ENGINE=InnoDB DEFAULT CHARSET=latin1;
-
-
-
-
-
-
-
-
-
- INSERTINTO `fact_logs` VALUES ('1', '1', '4', '1', '87');
-
- INSERTINTO `fact_logs` VALUES ('10', '2', '5', '2', '14');
-
- INSERTINTO `fact_logs` VALUES ('2', '1', '4', '2', '128');
-
- INSERTINTO `fact_logs` VALUES ('3', '3', '4', '1', '5');
-
- INSERTINTO `fact_logs` VALUES ('4', '4', '4', '2', '4');
-
- INSERTINTO `fact_logs` VALUES ('5', '5', '4', '2', '5');
-
- INSERTINTO `fact_logs` VALUES ('6', '6', '4', '2', '3');
-
- INSERTINTO `fact_logs` VALUES ('7', '2', '4', '2', '4');
-
- INSERTINTO `fact_logs` VALUES ('8', '5', '5', '2', '15');
-
- INSERT INTO `fact_logs` VALUES ('9','6', '5', '2', '13');
分析一个访问日志的事实表,有三个维度,站点、 IP 地址、日期。事实表记录的。
其中fact_logs是事实表,dim_ip,dim_site,dim_time分别代表三个维度表。
(3) 定义模式
可以使用schema-workbench生成AccessInfo.xml 将他复制到E:\apache-tomcat-7.0.40\webapps\mondrian\WEB-INF\queries
- <Schema name="Access record warehouse">
- <DimensiontypeDimensiontype="StandardDimension" visible="true" name="AccessTime">
- <HierarchyvisibleHierarchyvisible="true" hasAll="true" allMemberName="AllTime" primaryKey="id">
- <TablenameTablename="dim_time" alias="">
- </Table>
- <Level name="Sign Time"visible="true" table="dim_time"column="signinTime" internalType="String"uniqueMembers="true">
- </Level>
- </Hierarchy>
- </Dimension>
- <DimensiontypeDimensiontype="StandardDimension" visible="true" name="WebsiteNum">
- <HierarchyvisibleHierarchyvisible="true" hasAll="true" allMemberName="AllSite" primaryKey="id">
- <TablenameTablename="dim_site" alias="">
- </Table>
- <LevelnameLevelname="Sign Site" visible="true" table="dim_site"column="dSiteID" internalType="int"uniqueMembers="false">
- </Level>
- </Hierarchy>
- </Dimension>
- <DimensiontypeDimensiontype="StandardDimension" visible="true" name="UserIP">
- <HierarchyvisibleHierarchyvisible="true" hasAll="true" allMemberName="AllIP" primaryKey="id">
- <TablenameTablename="dim_ip" alias="">
- </Table>
- <LevelnameLevelname="Sign IP" visible="true" table="dim_ip"column="dip" type="String"uniqueMembers="false">
- </Level>
- </Hierarchy>
- </Dimension>
- <CubenameCubename="Access Analysis" visible="true"cache="true" enabled="true">
- <TablenameTablename="fact_logs" alias="">
- </Table>
- <DimensionUsagesourceDimensionUsagesource="Access Time" name="Access Time"visible="true" foreignKey="fTime">
- </DimensionUsage>
- <DimensionUsagesourceDimensionUsagesource="Website Num" name="WebSite Num"visible="true" foreignKey="fSiteID">
- </DimensionUsage>
- <DimensionUsagesourceDimensionUsagesource="User IP" name="User IP" visible="true"foreignKey="fIP">
- </DimensionUsage>
- <MeasurenameMeasurename="Amount" column="fCount" datatype="Integer"aggregator="sum" visible="true">
- </Measure>
- </Cube>
- </Schema>
(4) 负责展示层的编写 AccessInfo.jsp 他位于E:\apache-tomcat-7.0.40\webapps\mondrian\WEB-INF\queries
- <%@ page import="mondrian.olap.*"%>
- <%@ page session="true"contentType="text/html; charset=ISO-8859-1" %>
- <%@ tagliburi="http://www.tonbeller.com/jpivot" prefix="jp" %>
- <%@ taglib prefix="c"uri="http://java.sun.com/jstl/core" %>
-
- <jp:mondrianQuery id="query01"jdbcDriver="com.mysql.jdbc.Driver"jdbcUrl="jdbc:mysql://localhost/accessInfo"catalogUri="/WEB-INF/queries/AccessInfo.xml"
- jdbcUser="root" jdbcPassword="root" connectionPooling="false">
-
- select NON EMPTY {[Measures].[Amount]} ONCOLUMNS, NON EMPTY{([Access Time].[All Time], [Website Num].[All Site]) } ONROWS from [Access Analysis]
- where [User IP].[All IP].[61.144.207.115]
-
- </jp:mondrianQuery>
其中度量Mesures是具体的日志访问量(Amount),维度是Access Time,WebSite Num和User IP,展开和关闭All Time和All Site对应OLAP中的上钻和下钻操作,MDX中的where [UserIP].[61.144.207.115] 代表着一个切面,可以通过修改[User IP]下的值来获取不同切面下的time和site对应的日志访问量的值。