OLAP的学习与实例搭建
理论准备工作:
一. 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;
------------------------------
-- Tablestructure for `dim_ip`
------------------------------
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;
------------------------------
--Records of dim_ip
------------------------------
INSERTINTO `dim_ip` VALUES ('1', '61.183.248.218');
INSERTINTO `dim_ip` VALUES ('2', '61.144.207.115');
------------------------------
-- Tablestructure for `dim_site`
------------------------------
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;
------------------------------
--Records of dim_site
------------------------------
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');
------------------------------
-- Tablestructure for `dim_time`
------------------------------
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;
-- ----------------------------
--Records of dim_time
------------------------------
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');
------------------------------
-- Tablestructure for `fact_logs`
------------------------------
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;
-- ----------------------------
--Records of fact_logs
------------------------------
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
(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" %>
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]
其中度量Mesures是具体的日志访问量(Amount),维度是Access Time,WebSite Num和User IP,展开和关闭All Time和All Site对应OLAP中的上钻和下钻操作,MDX中的where [UserIP].[61.144.207.115] 代表着一个切面,可以通过修改[User IP]下的值来获取不同切面下的time和site对应的日志访问量的值。