EZDML 数据建模

超轻量级的免费数据建模工具

0%

EZDML连接hive数据仓库建模实践

理论上EZDML可以通过JDBC连接所有数据库,之前有网友跟我说EZDML通过JDBC连接hive有问题,我自己不玩数据仓库,对hive不熟,不过我想正常来说都是JDBC封装了,不应该啊。因此这几天我就亲自试验了一下,看看到底是什么情况。过程中发现要修改JDBC和EZDML代码,因此也记录一下相关的处理过程供参考。

先说结论:EZDML最新版3.42后可以连接hive,旧版有问题(本文是从旧版开始的,弄完这文章后新版才出来)。

安装hive

hive安装网上有很多文章了,这里简单介绍下我的安装过程,hive老手可以跳过这一节。

一开始是想自己从零开始安装的,不过这玩意确实有点复杂,各种版本引用问题,照着网上的文章折腾半天后,我觉得还是找个别人装好的镜像算了。

我找的是厦门大学数据库实验室林子雨老师的大数据Linux实验环境虚拟机镜像文件,里面已经安装好所需软件,内容非常全面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Ubuntu16.04
Hadoop2.7.1
Spark2.1.0
HBase1.1.5
JDK1.8
Scala2.11.8
MySQL
Kafka_2.11-0.10.2.0
Flume1.7.0
sbt
Maven3.3.9
MongoDB3.2.17
Hive2.1.0
Scala IDE(包含Eclipse4.7.0和Maven、Scala、sbt插件)

感谢林老师的奉献!下载地址:

1
http://dblab.xmu.edu.cn/blog/1645-2/

下载后会得到一个6G的ova公开虚拟机格式文件:

用VirtualBox或VMWare都可以导入打开,我是用VMWare:

有个警告,可以点“重试”忽略:

然后等上十几分钟,估计是在解压缩:

导入成功:

开机,原来是个优麒麟系统:

默认有三个用户,我们用hadoop,密码也是hadoop:

登录后看下IP:

然后在本机用putty之类的终端工具连接,我这里用MobaXterm(连不上的,可能要检查下防火墙之类的):

直接运行hive试试:

看起来是连接mysql的配置要改一下,运行以下命令:

1
2
cd /usr/local/hive/conf
vim hive-site.xml

按i进入编辑模式,修改JDBC连接的URL,按提示说明添加useSSL=false参数,然后Esc并输入:wq保存退出:

再次运行hive:

嗯,这会换了一个错误了,看起来是hadoop服务没启动,我们先运行/usr/local/hadoop/sbin/start-all.sh:

这时可以在浏览器访问50070和8088端口了:

再运行hive命令,可以成功进入hive的SQL命令行了:

hive测试OK了,我们启动metastore和hiveserver2服务:

1
2
hive --service metastore &
hive --service hiveserver2 &

当然,这两命令最好在本机运行,不然可能一不小心把终端关闭了进程就会结束。

使用beeline检测一下:

1
beeline -u jdbc:hive2://localhost:10000/default

报错说不允许访问,上网搜索了一下,要修改hadoop/etc/hadoop/core-site.xml,增加以下内容:

1
2
3
4
5
6
7
8
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>

另外,根据网上的文章,为防止权限问题,我们再编辑一下hadoop/etc/hadoop/hdfs-site.xml,添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
<description>
If "true", enable permission checking in HDFS.
If "false", permission checking is turned off,
but all other behavior is unchanged.
Switching from one parameter value to the other does not change the mode,
owner or group of files or directories.
</description>
</property>

保存,然后重启hadoop服务:

再次运行beeline检测,这回成功连接可以执行SQL命令了:

至此,hive的准备工作宣告完成。

测试JDBC连接hive

hive就绪后,我就尝试用EZDML连接。

我用的是EZDML for win64,首先找到EZDML的jdbc子目录下的conf.bat,将内容修改成这样:

1
2
3
4
5
6
7
8
9
10
11
@echo off

set java_bin=java.exe
set jdbc_driver=org.apache.hive.jdbc.HiveDriver
set jdbc_url=jdbc:hive2://192.168.172.135:10000/default
set jdbc_username=hive
set jdbc_password=hive
set jdbc_engineType=HIVE
set http_password=
set http_port=8083

然后双击运行ezjdbc.bat,结果如下:

嗯,加载driver失败。显然了,我是在windows下访问,是需要hive的JDBC驱动才能跑的。

这个驱动我瞎折腾了很久,过程不细说了,直接说结论:将hive虚拟机hadoop/share/hadoop/common/下子目录的hadoop-common-2.7.1.jar和hive/jdbc目录下的hive-jdbc-2.1.0-standalone.jar拷出来放到EZDML/jdbc/lib目录下就行了(MobaXterm可以直接把远程的文件拖出来,putty的话估计要用WinSCP下载):

最终运行连接成功:

JDBC服务启动成功了。

不过可能还需要其它JAR也是有的,我后来在调试过程中,有一回不小心调了下不知是什么参数,突然连接hive时提示NoClassDefFoundError: com/google/protobuf/ProtocolMessageEnum,只好又去虚拟机上拉了个protobuf-java-2.5.0.jar过来。

如果你用其它工具的JDBC能连上HIVE,也可以将ezjdbc.jar及相关文件拷过去运行(参考ezjdbc.bat)。

如果你是java程序员,你可以直接拉代码,修改pom.xml引用hive驱动,让maven帮你下载JAR包编译运行,这样你就不用操心驱动下载问题。

如果您在windows下跑EZDML,实在找不到可用的驱动,其实还有另一个办法,就是在hive服务器上直接运行,因为EZDML的JDBC服务本质上就是一个JAVA写的jar包,它是可以在linux下运行的(直接用EZDML for linux64也是可以的),而hive的服务器上既有java环境又有所有的jar包,直接用它自带的jar驱动肯定是没问题的。具体我这里就不展开了。

EZDML连接JDBC服务

(注:本节和下两节是使用EZDML之前的旧版3.41自带的ezjdbc.jar出错,新版本EZDML已经解决这个问题并可以直接连接了;保留此三节只是为了说明碰到问题时如何修改EZJDBC服务源码,大家不需要修改相关源码的可以跳过)

这时理论上应该可以用EZDML连接了,我们来试下:

果然连接出错了,Method not supported,大概意思是某个方法不支持。网友诚不我欺也,看下错误堆栈:

看起来是获取用户名出错了,免不了要改代码了。

拉取JDBC代码并搭建编译环境

(注:本节和上下节是使用EZDML之前的旧版3.41自带的ezjdbc.jar出错,新版本EZDML已经解决这个问题并可以直接连接了;保留此三节只是为了说明碰到问题时如何修改EZJDBC服务源码,大家不需要修改相关源码的可以跳过)

为方便有需要的朋友,我这里也演示下如何拉取EZDML的JDBC服务代码并搭建编译环境,熟练的可以跳过此节。

首先是从gitee获取最新的代码,最新的代码在这里可以获取到:

1
https://gitee.com/huzgd/ezdml/tree/master/jdbc/EzdmlJdbcServer

它隶属于ezdml仓库,用git克隆整个仓库:

1
https://gitee.com/huzgd/ezdml.git

然后在jdbc/EzdmlJdbcServer子目录下就能找到JDBC服务源码了:

我们用idea导入,这个工程导入后理论上是可以直接编译运行的:

不过,它需要设置运行参数,我们设置它的启动参数如下:

1
jdbc.driver=org.apache.hive.jdbc.HiveDriver jdbc.url=jdbc:hive2://192.168.172.135:10000/default jdbc.username=hive jdbc.password=hive jdbc.engineType=HIVE http.password= http.port=8083

再次运行:

嗯,缺JDBC驱动,我们把那两个jar拷到lib目录并加到工程里:

再次运行:

运行OK了,连上hive了,接下来我们看看如何调试修改。

调试修改JDBC代码

(注:本节和上两节是使用EZDML之前的旧版3.41自带的ezjdbc.jar出错,新版本EZDML已经解决这个问题并可以直接连接了;保留此三节只是为了说明碰到问题时如何修改EZJDBC服务源码,大家不需要修改相关源码的可以跳过)

编译运行起来后,我们再次用EZDML连接,果然又报“Method not supported”的错误了,错误堆栈代码定位在meta.getUserName这一行:

嗯,这个getUserName是为了告诉EZDML当前连接的用户模式名DbSchema,估计hive不支持这个,不过这个DbSchema不回传也没什么问题,我们直接把错误try掉,再试:

连接成功了,不过目前数据库是空的:

另外,我还修改了其它几处Java代码,包括导入map、array类型的,并增加了pom.xml,方便大家用maven下载驱动JAR包。

最新的JDBC服务代码已经提交到gitee,大家可以直接拉下来跑。

1
https://gitee.com/huzgd/ezdml/tree/master/jdbc/EzdmlJdbcServer

导入hive数据表

我们通过hive创建一个带中文注释的测试表:

1
2
3
4
5
6
7
8
9
10
CREATE TABLE IF NOT EXISTS employee (
eid int COMMENT '雇员ID',
name String COMMENT '姓名',
salary String COMMENT '工资',
destination String COMMENT '工作目标')
COMMENT '雇员信息'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;

然后再用EZDML导入:

确实导入成功了,不过,中文是乱码:

再检查一下,发现它自己的命令行出来也是乱码:

这就不是我的错了。上网搜索了一下,大概是因为mysql中存储的元数据不支持UTF8,需要在mysql中执行以下命令设置:

1
2
3
4
5
6
alter table TBLS modify column TBL_NAME  varchar(1000) character set utf8;
alter table COLUMNS_V2 modify column COMMENT varchar(256) character set utf8;
alter table TABLE_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
alter table PARTITION_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
alter table PARTITION_KEYS modify column PKEY_COMMENT varchar(4000) character set utf8;
alter table INDEX_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;

注意是MYSQL中执行:

执行完成,重新创建表,并检查,没有乱码了:

回到EZDML,再次导入,这回中文正常导入成功了:

EZDML新版支持HIVE

(注:本节中的问题是因为使用EZDML之前的旧版3.41导致,新版本EZDML已经解决了)

文章写到这里,到生成SQL时,突然发现接下来有点玩不下去了,因为hive的SQL语法跟关系数据库的有较大差异,EZDML生成的SQL没有一种是跟hive兼容的。而且hive还不支持类似 / * xxx * / 这种跨行的注释。

如何才能支持hive的SQL语法,我面临两个选择:

  1. 继承修改java代码,由JAVA代码实现对HIVE的支持(EZDML支持把生成SQL的工作交给JDBC服务,感兴趣的同学可在源码中搜索GenCustomSql)
  2. 直接修改EZDML的Pascal代码,增加一个全新的HIVE类型的数据库方言

我琢磨了半天,决定还是改EZDML的代码,增加对HIVE的支持。java代码虽然预留了自定义SQL功能,但那毕竟只是为了生成数据库SQL时作轻微小改动用的,HIVE这个我感觉要改的地方很多,还是花点时间折腾一下吧。

EZDML的核心代码上传到gitee了,因此也简单讲一下我如何添加HIVE的支持。

首先是修改DML/CtMetaTable.pas,添加HIVE的默认数据类型:

并在相关的地方添加判断引用(查找POSTGRESQL,把POSTGRESQL的所有代码复制一份改一下):

自定义数据类型设置也要相应增加:

表属性也加上,这时已经能生成SQL了:

不过细节还有点问题,string类型应该是不需要长度的,有长度的要转成varchar,我们修改一下TCtMetaField.GetPhyDataTypeName这个方法:

再生成就好了,不指定长度的字符串为string类型,有长度的则为varchar:

不过还是有一些问题,需要继续改进。

EZDML默认生成SQL的代码主要有两个地方,都是在DML/CtMetaTable.pas里:

  1. TCtMetaTable.GenSqlEx:生成创建表的SQL
  2. TCtMetaDatabase.GenObjSql:与数据库比较,生成修改表的SQL

我对其中一些内容为HIVE进行专门处理,大家在拉取新代码后查找HIVE就能找到我改过的地方了。

除了这两个地方,还有其它一些细节,这里就不一一展开了。总之最后我们改了一个新版本3.42出来,这个版本勉强支持HIVE了。

生成hive数据库SQL

我们再新建一个表,输入以下描述字内容(这里我加了map和array的演示字段):

1
2
3
4
5
6
7
8
9
10
11
12
13
MapTestTable(Map测试表)
------------------------------------------------------
id(编号) Integer
pid(父编号) Integer
rid(关联编号) Integer
name(名称) String(255)
desc2(描述) Object //<<类名:map<string&string> >>
tslist(测试列表) List //<<类名:array<string> >>
creatorid(创建人编号) Integer //创建人编号 当前用户ID
creatorname(创建人姓名) String(2147483647)
createdate(创建日期) Date //创建日期 默认为当前时间
datalevel(数据级别) Integer //数据级别 0正常 1审核中 2被否决 -1已删除 -2草稿
orderno(排序号) Float(15,15)

生成数据库SQL:

执行:

然后我试着把EZDML自带的demo文件的第一个模型图也生成了一下(先要关闭SQL生成设置里保留字的引号),执行也是OK的:

至此HIVE数据库生成完毕。试了下执行select SQL查看数据,也是可以的:

另外也试了一下生成测试数据的SQL,不过执行insert语句的速度太慢了,insert一条记录居然要十几二十秒,没什么意义,还是用Load data指令加载文件靠谱。

小结

EZDML能支持HIVE了,你需要使用3.42以上版本的EZDML,带最新的ezjdbc.jar(EzdmlJdbcServer),你还需要有hive的JDBC驱动相关的一堆jar,虽然还比较麻烦,效果也不完美,但总算是从无到有零的突破了。