OLAP实现的例子 数据结构数据挖掘应用服务器SQLSQL Server
//这个代码片段中实现的是MOLAP,关于MOLAP和ROLAP参见下面索引1
//创建一个OLAP执行引擎
OlapEngine olap = new OlapEngine();
//读取原始的数据文件
//由于原始的文件为csv文件,所以没有元数据(metadata),要进行对数据的格式识别,参见下面索引2
MiningStream inputStream = new MiningCsvStream("c:\\a.csv");
//数据a.csv文件请参见下面索引3
//数据流的读入,采用的是数据完全读入的方式,但是这一步的主要的工作只是增加元数据
inputStream.open();
//把数据流放入OLAP执行引擎
olap.setInputStream(inputStream);
//创建要建立的OLAP数据服务
//从OLAP执行引擎取得数据维对象
DimensionClass dimClass = (DimensionClass) olap.getDimension();
//数据维对象创建
//可以通过inputStream.getMeta()方法取出所有的可供使用的列属性
//dimClass.createDimension(该数据维的名称,inputStream的列属性名)
Dimension product = dimClass.createDimension("Product", "product");
Dimension time = dimClass.createDimension("Time", "time");
Dimension channel = dimClass.createDimension("Channel", "channel");
Dimension salesDim = dimClass.createDimension("SalesDim", "sales");
//创建了父子关系的维。
Dimension geog = dimClass.createHierachicalDimension("Geography");
geog.addInputAttribute( olap.getInputAttribute("country") ); // 0层
geog.addInputAttribute( olap.getInputAttribute("city") ); // 1层
//新建一个数据维,这个数据维是(sales-cost)的组成的
MeasureClass measClass = (MeasureClass) olap.getMeasure();
Measure sales = measClass.createAggregationMeasure("Sales",
olap.getInputAttribute("sales") );
Measure cost = measClass.createAggregationMeasure("Cost",
olap.getInputAttribute("cost") );
Measure profit = measClass.createBinaryOperatorMeasure("Profit",
BinaryOperatorMeasure.MINUS, sales, cost);
// 建立运有运算的维数据
//这里只是简单的把属性增加到维数据中,并不真正的进行运算
Dimension meas = dimClass.createMeasureDimension("Measures");
meas.addInputAttribute(sales);
meas.addInputAttribute(cost);
meas.addInputAttribute(profit);
//从OLAP服务器中建立所有可供使用的多维数据结构(schema)
SchemaClass schemaClass = (SchemaClass) olap.getSchema();
Schema dimensionalSchema = schemaClass.createSchema("All");
//把所有的维数据增加到多维的数据结构
dimensionalSchema.addDimension(product);
dimensionalSchema.addDimension(geog);
dimensionalSchema.addDimension(time);
dimensionalSchema.addDimension(channel);
dimensionalSchema.addDimension(meas);
dimensionalSchema.addDimension(salesDim);
//从OLAP服务器中建立建立数据立方体
CubeClass cubeClass = (CubeClass) olap.getCube();
Cube salesCube = cubeClass.createCube("Sales Cube");
//本数据立方体中只使用以下的数据维
salesCube.addDimension(product);
salesCube.addDimension(geog);
salesCube.addDimension(time);
salesCube.addDimension(channel);
salesCube.addDimension(meas);
//增加Cube到多维的数据结构(Schema)
dimensionalSchema.addCube(salesCube);
//增加Schema到OLAP服务器中
olap.setCurrentSchema(dimensionalSchema);
//执行OLAP的初始化
//所有OLAP数据读入到建立数据立方体
olap.init();
//输出元数据和多维的数据结构
MiningDataSpecification metaData = olap.getMultMetaData();
System.out.println("metaData=" + metaData);
// metaData=relation: 'transformed_c:\\a.csv'
// 0.cat_city, type: categorical, categories: {123, 231, 13, 214, 24}, unboundedCategories, dataType: string
// 1.cat_time, type: categorical, categories: {123, 324, 33, 22, 34}, unboundedCategories, dataType: string
// 2.cat_channel, type: categorical, categories: {123, 313, 443, 33, 24}, unboundedCategories, dataType: string
// 3.cat_sales, type: categorical, categories: {123, 1243, 13, 1314, 356}, unboundedCategories, dataType: string
// 4.product, type: categorical, categories: {abc1, abc, www}, unboundedCategories, dataType: string
// 5.time, type: numeric, (-Infinity,Infinity), dataType: double
// 6.channel, type: numeric, (-Infinity,Infinity), dataType: double
// 7.sales, type: numeric, (-Infinity,Infinity), dataType: double
// 8.country, type: categorical, categories: {Greece, ww}, unboundedCategories, dataType: string
// 9.city, type: numeric, (-Infinity,Infinity), dataType: double
// 10.cost, type: numeric, (-Infinity,Infinity), dataType: double
//(由于是对CSV文件中没有元数据,进行格式识别中,同时存在了同一字段的两种可能,所以cat_开头的表示,同时可能是Categorical类型和Numeric类型)
System.out.println("schema: " + dimensionalSchema);
// schema: Schema name = All
// #dimensions = 6 :
// Dimension name = Product
// #attributes = 1 : product
//
// Dimension name = Geography
// #attributes = 2 : country, city
// #hierarchies = 1 :
// LevelBasedHierarchy name = Standard
// #hierarchyLevelAssociation = 2 :
// HierarchyLevelAssociation: currentLevel name = country
// HierarchyLevelAssociation: currentLevel name = city
//
//
// Dimension name = Time
// #attributes = 1 : time
//
// Dimension name = Channel
// #attributes = 1 : channel
//
// Dimension name = Measures
// #attributes = 3 : Sales, Cost, Profit
//
// Dimension name = SalesDim
// #attributes = 1 : sales
//
//
// #cubes = 1 :
// Cube name = Sales Cube
// #cubeDimensionAssociations = 5 :
// CubeDimensionAssociation: dimension name = Product
// CubeDimensionAssociation: dimension name = Geography
// CubeDimensionAssociation: dimension name = Time
// CubeDimensionAssociation: dimension name = Channel
// CubeDimensionAssociation: dimension name = Measures
//以下是针对Cube的查询了
// 为每个维建立维视图
DimensionView channelView = (DimensionView) olap.createDimensionView();
channelView.setDimension(channel);
DimensionView productView = (DimensionView) olap.createDimensionView();
productView.setDimension(product);
DimensionView geographyView = (DimensionView) olap.createDimensionView();
geographyView.setDimension(geog);
DimensionView timeView = (DimensionView) olap.createDimensionView();
timeView.setDimension(time);
MeasureView measView = (MeasureView) olap.createMeasureView();
measView.setDimension(meas);
//针对salesCube数据建立Cube视图
CubeView query = (CubeView) olap.createCubeView(salesCube);
// EdgeView表示一个维的指针
EdgeView columns1 = (EdgeView) query.createOrdinateEdge();
//这个维中增加了geographyView,productView两个维
columns1.addDimensionView(geographyView);
columns1.addDimensionView(productView);
//第二个维指针
EdgeView columns2 = (EdgeView) query.createOrdinateEdge();
columns2.addDimensionView(timeView);
//数据切片的维指针,只显示了measView的切片数据
EdgeView pages = (EdgeView) query.createPageEdge();
pages.addDimensionView(measView);
//建立一个数据查询指针
CubeCursor dataCursor = (CubeCursor) query.createCursor();
System.out.println("aggregateStream: " + dataCursor.getResultTable());
//aggregateStream: relation: attMetaData
//0.country, type: categorical, categories: {Greece, ww}, unboundedCategories, dataType: string
//1.product, type: categorical, categories: {abc1, abc, www}, unboundedCategories, dataType: string
//2.cat_time, type: categorical, categories: {123, 324, 33, 22, 34}, unboundedCategories, dataType: string
//3.Sales, type: numeric, (-Infinity,Infinity), dataType: double
//4.Cost, type: numeric, (-Infinity,Infinity), dataType: double
//5.Profit, type: numeric, (-Infinity,Infinity), dataType: double
// 取得所有的切片维指针
EdgeCursor pageCursor = (EdgeCursor) dataCursor.getPageEdge().iterator().next();
//取得两个维指针
//columns1
EdgeCursor columnCursor1 = (EdgeCursor) dataCursor.getOrdinateEdge().get(0);
//columns2
EdgeCursor columnCursor2 = (EdgeCursor) dataCursor.getOrdinateEdge().get(1);
//以下就是激动人心的,另人兴奋的,扣人心弦的,OLAP的查询功能了
columnCursor1.beforeFirst();
while (columnCursor1.next()) {
System.out.println("--" + columnCursor1.read() + "--");
columnCursor2.beforeFirst();
while (columnCursor2.next()) {
System.out.println("==" + columnCursor2.read() + "==");
pageCursor.beforeFirst();
while (pageCursor.next())
System.out.println("三三"+pageCursor.read()+"三三");
}
}
//以下是查询的结果:
// --"ww","www"--
// =="34"==
// 三三"ww","www","34",356.0,356.0,0.0三三
// =="22"==
// 三三"ww","www","22",1314.0,244.0,1070.0三三
// =="123"==
// =="33"==
// =="324"==
// --"Greece","abc1"--
// =="34"==
// =="22"==
// =="123"==
// 三三"Greece","abc1","123",123.0,123.0,0.0三三
// =="33"==
// =="324"==
// --"Greece","abc"--
// =="34"==
// =="22"==
// =="123"==
// =="33"==
// 三三"Greece","abc","33",13.0,13.0,0.0三三
// =="324"==
// 三三"Greece","abc","324",1243.0,31.0,1212.0三三
//分析第一个维的指针
columns1.addDimensionView(geographyView); aa.csv文件中可以看出只可能取值为{ww,Greece}
columns1.addDimensionView(productView); aa.csv文件中可以看出只可能取值为{www,abc,abc1} (aa.csv文件在最下面)
//分析第二个维的指针
columns2.addDimensionView(timeView); aa.csv文件中可以看出只可能取值为{34,123,324,33,22}
//分析切片的维
pages.addDimensionView(measView); aa.csv文件中为sales - cost构成
第一个维先走,输出--"ww","www"--
第二个维走下,输出=="34"==
然后查询切片数据,geographyView=ww,productView=www,timeView=34时 得到sales=356,cost=356,sales - cost=0
输出 三三"ww","www","34",356.0,356.0,0.0三三
(程序内部也是这样干的)
//建立针对维的指针
DimensionCursor measureCursor = (DimensionCursor) pageCursor.getDimensionCursor().get(0);
DimensionCursor productCursor = (DimensionCursor) columnCursor2.getDimensionCursor().get(0);
DimensionCursor geographyCursor = (DimensionCursor) columnCursor1.getDimensionCursor().get(0);
DimensionCursor timeCursor = (DimensionCursor) columnCursor1.getDimensionCursor().get(1);
geographyCursor.beforeFirst();
while (geographyCursor.next()) {
System.out.println("geog: " + geographyCursor.getString(1));
timeCursor.beforeFirst();
while (timeCursor.next()) {
System.out.println("time: " + timeCursor.getString(1));
productCursor.beforeFirst();
while ( productCursor.next() ) {
System.out.println( "prod: " + productCursor.getString(1) );
measureCursor.beforeFirst();
while ( measureCursor.next() ) {
for (int i = 0; i < measureCursor.getMetaData().getColumnCount(); i++)
System.out.print(measureCursor.getDouble(i + 1) + " ");
System.out.println();
}
}
}
以下的为输出,大家自已分析吧
// geog: ww
// time: www
// prod: 34
// 356.0 356.0 0.0
// prod: 22
// 1314.0 244.0 1070.0
// prod: 123
// prod: 33
// prod: 324
// geog: Greece
// time: abc1
// prod: 34
// prod: 22
// prod: 123
// 123.0 123.0 0.0
// prod: 33
// prod: 324
// time: abc
// prod: 34
// prod: 22
// prod: 123
// prod: 33
// 13.0 13.0 0.0
// prod: 324
// 1243.0 31.0 1212.0
}
索引1:
OLAP系统按照其存储器的数据存储格式可以分为关系OLAP(RelationalOLAP,简称ROLAP)、
多维OLAP(MultidimensionalOLAP,简称MOLAP)和混合型OLAP(HybridOLAP,简称HOLAP)三种类型。
1.ROLAP
ROLAP将分析用的多维数据存储在关系数据库中并根据应用的需要有选择的定义一批实视图作为表也存储在关系数据库中。
不必要将每一个SQL查询都作为实视图保存,只定义那些应用频率比较高、计算工作量比较大的查询作为实视图。
对每个针对OLAP服务器的查询,优先利用已经计算好的实视图来生成查询结果以提高查询效率。
同时用作ROLAP存储器的RDBMS也针对OLAP作相应的优化,比如并行存储、并行查询、并行数据管理、基于成本的查询优化、
位图索引、SQL的OLAP扩展(cube, rollup)等等。
2. MOLAP
MOLAP将OLAP分析所用到的多维数据物理上存储为多维数组的形式,形成“立方体”的结构。
维的属性值被映射成多维数组的下标值或下标的范围,而总结数据作为多维数组的值存储在数组的单元中。
由于MOLAP采用了新的存储结构,从物理层实现起,因此又称为物理OLAP(Physical OLAP);
而ROLAP主要通过一些软件工具或中间软件实现,物理层仍采用关系数据库的存储结构,因此称为虚拟OLAP(Virtual OLAP)。
索引2:
格式一共有三种可能:
分别为1,字符型数据(Categorical)(例如:服装的东西的数据:衣服,裤子,帽子,鞋)要在元数据中完成列出数据的所有可能的值
2,有顺序的字符型数据(Ordinal)(例如:天气的数据:晴,多云,阴,下雨)最好要标明数据的方向(从小到大,还是从大到小)
3,数值数据(Numeric)(例如:身高的数据:175CM,160CM,185CM)要指定数据的值域范围
数据的以上三种分类,spss,weka,prefuse都是这样划分的
1 在对于数据的使用中,最好用户手动定义元数据
2 对于没有元数据的文件识别,优先度Numeric > Ordinal > Categorical.
3 数据挖掘中,特定的算法只能指定某种数据类型,所以常常需要进行以上三种数据类型的转化
一般只能从Numeric > Ordinal > Categorical按从左到右的方向转化
Numeric转化为Ordinal,常常是划分区间,如果Numeric集中在1~100之间,可以把1~100分成N个区间,1~20,20~40,把Numeric对应到各个区间上
索引3:
a.csv文件
product time channel sales country city cost
abc1 123 123 123 Greece 123 123
abc 324 313 1243 Greece 231 31
abc 33 443 13 Greece 13 13
www 22 33 1314 ww 214 244
www 34 24 356 ww 24 356
如果有什么问题请留言,自已正在钻研OLAP,看的代码很乱,自已只是提取了一个例子总结一下,
这个例子中内部OLAP如何进行查询的以后再写,现在还有一个地方没有搞明白。