需求描述

考虑直接在Hive或者Impala等Big Data方案,能够支持MDX查询,现调研一下Mondrian对hive的支持情况。

环境准备

hive环境,采用hive-0.10-cdh4.2.1 客户端程序使用的类库:mondrian-3.6.0、olap4j-1.2.0-SNAPSHOT

数据准备

来源于网上一个数据源,准备四张表 Customer - 客户信息维表 Product - 产品维表 ProductType - 产品类表维表 Sale - 销售记录表 为了方便测试数据与MDX正确性,将数据导入到MySQL中一份,用来与Hive查询结果进行对比。

在MySQL创建对应表及数据

具体SQL语句:

create database hive_test;

use hive_test;

/**用户信息表*/
create table Customer (
cusId int not null,
gender char(1) null,
constraint PK_CUSTOMER primary key(cusId)
); /**产品表*/
create table Product (
proId int not null,
proTypeId int null,
proName varchar(32) null,
constraint PK_PRODUCT primary key(proId)
); /**产品类别表*/
create table ProductType (
proTypeId int not null,
proTypeName varchar(32) null,
constraint PK_PRODUCTTYPE primary key (proTypeId)
); /**销售记录表/
create table Sale (
saleId int not null,
proId int null,
cusId int null,
unitPrice float null,
number int null,
constraint PK_SALE primary key(saleId)
); insert into Customer(cusId,gender) values(1,'F');
insert into Customer(cusId,gender) values(2,'M');
insert into Customer(cusId,gender) values(3,'M');
insert into Customer(cusId,gender) values(4,'F'); insert into ProductType(proTypeId,proTypeName) values(1,'electrical');
insert into ProductType(proTypeId,proTypeName) values(2,'digital');
insert into ProductType(proTypeId,proTypeName) values(3,'furniture'); insert into Product(proId,proTypeId,proName) values(1,1,'washing machine');
insert into Product(proId,proTypeId,proName) values(2,1,'television');
insert into Product(proId,proTypeId,proName) values(3,2,'mp3');
insert into Product(proId,proTypeId,proName) values(4,2,'mp4');
insert into Product(proId,proTypeId,proName) values(5,2,'camera');
insert into Product(proId,proTypeId,proName) values(6,3,'chair');
insert into Product(proId,proTypeId,proName) values(7,3,'desk');
insert into sale(saleId,proId,cusId,unitPrice,number) values(1,1,1,340.34,2);
insert into sale(saleId,proId,cusId,unitPrice,number) values(2,1,2,140.34,1);
insert into sale(saleId,proId,cusId,unitPrice,number) values(3,2,3,240.34,3);
insert into sale(saleId,proId,cusId,unitPrice,number) values(4,3,4,540.34,4);
insert into sale(saleId,proId,cusId,unitPrice,number) values(5,4,1,80.34,5);
insert into sale(saleId,proId,cusId,unitPrice,number) values(6,5,2,90.34,26);
insert into sale(saleId,proId,cusId,unitPrice,number) values(7,6,3,140.34,7);
insert into sale(saleId,proId,cusId,unitPrice,number) values(8,7,4,640.34,28);
insert into sale(saleId,proId,cusId,unitPrice,number) values(9,6,1,140.34,29);
insert into sale(saleId,proId,cusId,unitPrice,number) values(10,7,2,740.34,29);
insert into sale(saleId,proId,cusId,unitPrice,number) values(11,5,3,30.34,28);
insert into sale(saleId,proId,cusId,unitPrice,number) values(12,4,4,1240.34,72);
insert into sale(saleId,proId,cusId,unitPrice,number) values(13,3,1,314.34,27);
insert into sale(saleId,proId,cusId,unitPrice,number) values(14,3,2,45.34,27);

hive中测试数据准备

在虚拟机准备好hive测试环境,采用hive-0.10-cdh4.2.1版本 具体语句:

create database mondrian;
use mondrian;
create table Sale (saleId INT, proId INT, cusId INT, unitPrice FLOAT, number INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY ",";
create table Product (proId INT, proTypeId INT, proName STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ",";
create table ProductType (proTypeId INT, proTypeName STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ",";
create table Customer (cusId INT, gender STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ","; # Customer文件
1,F
2,M
3,M
4,F
load data local inpath "/home/hzwangxx/cdh4/hive/myTmp/Customer" OVERWRITE into table Customer; # ProductType文件
1,electrical
2,digital
3,furniture
load data local inpath "/home/hzwangxx/cdh4/hive/myTmp/ProductType" into table ProductType; # Product数据文件
1,1,washing machine
2,1,television
3,2,mp3
4,2,mp4
5,2,camera
6,3,chair
7,3,desk
load data local inpath "/home/hzwangxx/cdh4/hive/myTmp/Product" into table Product; # Sale数据文件
1,1,1,340.34,2
2,1,2,140.34,1
3,2,3,240.34,3
4,3,4,540.34,4
5,4,1,80.34,5
6,5,2,90.34,26
7,6,3,140.34,7
8,7,4,640.34,28
9,6,1,140.34,29
10,7,2,740.34,29
11,5,3,30.34,28
12,4,4,1240.34,72
13,3,1,314.34,27
14,3,2,45.34,27
load data local inpath "/home/hzwangxx/cdh4/hive/myTmp/Sale" into table Sale;

元数据定义

Cube、Measure等元数据定义见:

<Schema name="hello">
<Cube name="Sales">
<!-- 事实表(fact table) -->
<Table name="Sale"/>
<!-- 客户维 -->
<Dimension name="cusGender" foreignKey="cusId">
<Hierarchy hasAll="true" allMemberName="allGender" primaryKey="cusId">
<Table name="Customer"/>
<Level name="gender" column="gender"/>
</Hierarchy>
</Dimension>
<!-- 产品类别维 -->
<Dimension name="proType" foreignKey="proId">
<Hierarchy hasAll="true" allMemberName="allPro" primaryKey="proId" primaryKeyTable="Product">
<join leftKey="proTypeId" rightKey="proTypeId">
<Table name="Product"/>
<Table name="ProductType"/>
</join>
<Level name="proTypeId" column="proTypeId" nameColumn="proTypeName" uniqueMembers="true" table="ProductType"/>
<Level name="proId" column="proId" nameColumn="proName" uniqueMembers="true" table="Product"/>
</Hierarchy>
</Dimension>
<Measure name="numb" column="number" aggregator="sum" datatype="Numeric"/>
<Measure name="totalSale" aggregator="sum" formatString="$ #,##0.00">
<!-- unitPrice*number所得值的列 -->
<MeasureExpression>
<SQL dialect="generic">unitPrice*number</SQL>
</MeasureExpression>
</Measure>
<CalculatedMember name="averPri" dimension="Measures">
<Formula>[Measures].[totalSale] / [Measures].[numb]</Formula>
<CalculatedMemberProperty name="FORMAT_STRING" value="$ #,##0.00"/>
</CalculatedMember>
</Cube>
</Schema>

测试MDX

1. 查询所有类别产品销售总件数、平均价格和总销售额

"select " + "{[Measures].[numb],[Measures].[averPri],[Measures].[totalSale]} on columns," + "{([proType].[allPro],[cusGender].[allGender])} " + "on rows " + "from [Sales]" 

对Hive支持情况

建立Connection连接方式

建立Connection连接方式有两种:

使用mondrian自带的DriverManager获取Connection实例

mondrian中自带的API

# 这里的Connection、DriverManager、Query、Result等都是mondrian提供的API接口
Connection connection = DriverManager.getConnection(
"Provider=mondrian;" +
"Jdbc=jdbc:hive2://node02:10000/mondrian;" +
"JdbcUser=;JdbcPassword=;" +
"Catalog=/Users/apple/IdeaProjects/hbase-manage/src/main/resources/MiniMart.xml;" +
"JdbcDrivers=org.apache.hive.jdbc.HiveDriver", null); Query query = connection.parseQuery(
"select \n" +
"{[Measures].[numb],[Measures].[averPri],[Measures].[totalSale]} on columns,\n" +
"{([proType].[allPro],[cusGender].[allGender])} \n" +
"on rows\n" +
"from [Sales]\n"); @SuppressWarnings("deprecation")
Result result = connection.execute(query);
PrintWriter pw = new PrintWriter(System.out);
result.print(pw);
pw.flush();

  对应的连接MySQL,只需要将getConnection中的connectString换成如下即可:

Connection connection =  DriverManager.getConnection(
"Provider=mondrian;" +
"Jdbc=jdbc:mysql://localhost:3306/hive_test; JdbcUser=root;" +
"JdbcPassword=123;" +
"Catalog=/Users/apple/IdeaProjects/hbase-manage/src/main/resources/MiniMart.xml;" +
"JdbcDrivers=com.mysql.jdbc.Driver", null);

  测试的时候连接MySQL时,没什么问题,在使用相同的API连Hive的时候,有点问题。down了一下源码发现它的过程是这样的:先去连接池中取一个Connection实例,没有的话通过Factory创建一个Connection放入池里。而在Mondrian创建Factory的时候指定了两个属性:autoCommit和readOnly,RDBMS的Driver都没什么问题,Hive的JDBC提供的HiveConnection中对这两个属性的set方法实现得很诡异,都是直接抛异常了:

  public void setReadOnly(boolean readOnly) throws SQLException {
// TODO Auto-generated method stub
throw new SQLException("Method not supported");
}
public void setAutoCommit(boolean autoCommit) throws SQLException {
if (autoCommit) {
throw new SQLException("enabling autocommit is not supported");
}
}

将这两行抛出异常的地方注释掉,rebuild一下jar包,MDX就可以顺利执行完了。

使用JDK原生的DriverManager获取Connection实例

  可以使用JDK原生的DriverManager获取Connection然后再使用Olap4j的封装成OLapConnection然后再去执行MDX 具体连接示例如下:

 Class.forName("mondrian.olap4j.MondrianOlap4jDriver");
Connection nativeConn = DriverManager.getConnection("jdbc:mondrian:Jdbc=jdbc:hive2://node02:10000/mondrian; JdbcUser=;" +
"JdbcPassword=;" +
"Catalog=/Users/apple/IdeaProjects/hbase-manage/src/main/resources/MiniMart.xml;" +
"JdbcDrivers=org.apache.hive.jdbc.HiveDriver"); OlapConnection olapConn = nativeConn.unwrap(OlapConnection.class); if (olapConn == null) {
throw new IllegalStateException("Connection is null");
}
OlapStatement statement = olapConn.createStatement();
CellSet cellSet = statement.executeOlapQuery("select " +
"{[Measures].[numb],[Measures].[averPri],[Measures].[totalSale]} on columns," +
"{([proType].[allPro],[cusGender].[allGender])} " +
"on rows " +
"from [Sales]") ;
//formatter.
RectangularCellSetFormatter formatter =
new RectangularCellSetFormatter(false); // Print out.
PrintWriter writer = new PrintWriter(System.out);
formatter.format(cellSet, writer);
writer.flush();
statement.close();
olapConn.close();
nativeConn.close();

指定Database

  hive也有类似RDBMS一样有database的概念,在Hive提供的普通Java API中虽然在连接字符串中指定了database,但是它默认的并非你指定的database而是上一次当前客户端或线程使用的database(注:并非default),所以一般使用Hive 客户端必须先执行一下use database。而在OlapConnection和Mondrian提供的Connection都不支持"use database"操作。暂时的解决办法,每次去进行MDX查询的时候先通过普通的Java Api执行一下use database,指定到当前需要查询的数据库中。

Pentaho的Mondrian对Hive的支持的更多相关文章

  1. HIVE 不支持group by 别名

    hive不支持group by 别名,如果需要group by 别名的情况,可以使用 别名的 值作为group by 的值

  2. Hive不支持非相等的join

    由于 hive 与传统关系型数据库面对的业务场景及底层技术架构都有着很大差异,因此,传统数据库领域的一些技能放到 Hive 中可能已不再适用.关于 hive 的优化与原理.应用的文章,前面也陆陆续续的 ...

  3. Hbase对hive的支持没有hdfs的好的原因 及hbase什么时候使用 及rowkey设计技巧

    hive-=mareduce 的  split  在 hbase就是  region了,,,,,,,访问region必须通过hregionserver 会造成regionser负担过大, 另外 reg ...

  4. hive表支持中文设置

    默认创建表时说明中带有中文字段时会显示如下乱码信息: 解决方案: 在hive的元数据库中执行以下SQL语句,然后重新创建刚才的表即可 . ) character set utf8; ) charact ...

  5. hive支持in用法是从0.3.2版本后

    写hive 用in 如分时段,分类型,分平台统计点击量 select substr(createtime,12,2) hour,logtype,os_id,count(*)  from  wizad_ ...

  6. hive支持sql大全(收藏版)

    hive操作数据库还是比较方便的,因此才会有hbase与hive整合.下面我们hive的强大功能吧.为了增强阅读性,下面提几个问题: 1.hive支持哪些运算符? 2.hive是否支持左右连接? 3. ...

  7. Hive ACID和事务表支持详解

    一.ACID介绍 ACID就是常见数据库事务的四大特性:Atomicity(原子性).Consistency(一致性).Isolation(隔离性).Durability(持久性). 在Hive 0. ...

  8. hive中对子查询如in,exists等支持

    案例情况:同事使用公司数据探查跑一段代码,部分代码如下,报错,显示不支持in内的子查询.但是直接用虚拟机去跑的话代码没有任何报错,也出结果,很奇怪. SELECT t1.SIGN_CODE AS bu ...

  9. 基于Ubuntu Hadoop的群集搭建Hive

    Hive是Hadoop生态中的一个重要组成部分,主要用于数据仓库.前面的文章中我们已经搭建好了Hadoop的群集,下面我们在这个群集上再搭建Hive的群集. 1.安装MySQL 1.1安装MySQL ...

随机推荐

  1. 《杜增强讲Unity之Tanks坦克大战》7-坦克血条

    7 坦克血条 点击菜单GameObject->UI->Slider创建Slider   选中EventSystem,设置Horizontal Axis为HorzontalUI,Vertic ...

  2. Unity优化方向——优化Unity游戏中的图形渲染(译)

    CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...

  3. WebStorm微信小程序单位rpx出现空格问题

    Windows先下载sed 配置Tools->File Watchers->+ 添加下图配置 //windows系统 -i s/"\ rpx"/rpx/g $FileP ...

  4. Java那些事-泛型通配符

    Java的类型通配符,可以出现在类.方法上面.最常用的方式就是集合类,例如List,Set等类上面. 通配符类型 有泛型参数 List 有无类型标识 List< ? > 有通用的标识 Li ...

  5. mongodb基本使用(四)

    MongoDB 条件操作符 描述 条件操作符用于比较两个表达式并从mongoDB集合中获取数据. MongoDB中条件操作符有: (>) 大于 - $gt (<) 小于 - $lt (&g ...

  6. Python基础_内置函数

        Built-in Functions     abs() delattr() hash() memoryview() set() all() dict() help() min() setat ...

  7. Chapter 10 软件测试

    软件测试是软件质量保证的一项关键活动,验证与确认是贯穿软件生命周期的规范化评估方法.软件验证则试图证明在软件生存的各个阶段是否满足客户的需求,软件确认是一系列的活动和过程,两个活动相互独立但却相辅相成 ...

  8. Ubuntu恢复被误删的文件

    主要内容转载自博客:https://blog.csdn.net/YLD10/article/details/80241160 写在前面,该方法只能用于误删的文件,若文件被覆盖,则无法恢复. 1.下载工 ...

  9. week3a:个人博客作业

    1.博客上的问题 阅读下面程序,请回答如下问题: using System; using System.Collections.Generic; using System.Text; namespac ...

  10. 转 彻底理解js中的&&和||

    javascript中,&&和||的用法比较神奇,经常用在对象上,例如a || b,如果a不存在,则返回b.a && b,如果a存在,则返回b,否则返回a. 光这样看, ...