HBase与Hive的集成
HBase 虽然可以存储数亿或数十亿行数据,但是对于数据分析来说,不太友好,只提供了简单的基于 Key 值的快速查询能力,没法进行大量的条件查询。
不过,Hive 与 HBase 的整合可以实现我们的这个目标。不仅如此,还能通过 Hive 将数据批量地导入到 HBase 中。
Hive 与 HBase 整合的实现是利用两者本身对外的 API 接口互相通信来完成的,其具体工作交由 Hive 的 lib 目录中的 hive-hbase-handler-xxx.jar
工具类来实现对 HBase 数据的读取。
一,HBase与Hive的对比
-
Hive
(1) 数据仓库
Hive的本质其实就相当于将HDFS中已经存储的文件在Mysql中做了一个双射关系,以方便使用HQL去管理查询。
(2) 用于数据分析、清洗
Hive适用于离线的数据分析和清洗,延迟较高。
(3) 基于HDFS、MapReduce
Hive存储的数据依旧在
DataNode
上,编写的HQL语句终将是转换为MapReduce代码执行。 -
HBase
(1) 数据库
是一种面向列存储的非关系型数据库。
(2) 用于存储结构化和非结构化的数据
适用于单表非关系型数据的存储,不适合做关联查询,类似JOIN等操作。
(3) 基于HDFS
数据持久化存储的体现形式是
Hfile
,存放于DataNode
中,被ResionServer以region的形式进行管理。(4) 延迟较低,接入在线业务使用
面对大量的企业数据,HBase可以直线单表大量数据的存储,同时提供了高效的数据访问速度。
二,Hive与HBase整合的适用场景
- 通过 Hive 与 HBase 整合,可以将 HBase 的数据通过 Hive 来分析,让 HBase 支持 JOIN、GROUP 等 SQL 查询语法。
- 实现将批量数据导入到 HBase 表中。
三,HBase与Hive集成使用
注意:HBase与Hive的集成在最新的两个版本中无法兼容。所以,只能重新编译:hive-hbase-handler-1.2.2.jar(jar重新编译打包后,需要重启hive)
CDH版本的环境已经自动进行兼容了,不需要重新编译.
1.环境准备
因为我们后续可能会在操作Hive的同时对HBase也会产生影响,所以Hive需要持有操作HBase的Jar,那么接下来拷贝Hive所依赖的Jar包(或者使用软连接的形式)。
export HBASE_HOME=/opt/module/hbase
export HIVE_HOME=/opt/module/hive
ln -s $HBASE_HOME/lib/hbase-common-1.3.1.jar $HIVE_HOME/lib/hbase-common-1.3.1.jar
ln -s $HBASE_HOME/lib/hbase-server-1.3.1.jar $HIVE_HOME/lib/hbase-server-1.3.1.jar
ln -s $HBASE_HOME/lib/hbase-client-1.3.1.jar $HIVE_HOME/lib/hbase-client-1.3.1.jar
ln -s $HBASE_HOME/lib/hbase-protocol-1.3.1.jar $HIVE_HOME/lib/hbase-protocol-1.3.1.jar
ln -s $HBASE_HOME/lib/hbase-it-1.3.1.jar $HIVE_HOME/lib/hbase-it-1.3.1.jar
ln -s $HBASE_HOME/lib/htrace-core-3.1.0-incubating.jar $HIVE_HOME/lib/htrace-core-3.1.0-incubating.jar
ln -s $HBASE_HOME/lib/hbase-hadoop2-compat-1.3.1.jar $HIVE_HOME/lib/hbase-hadoop2-compat-1.3.1.jar
ln -s $HBASE_HOME/lib/hbase-hadoop-compat-1.3.1.jar $HIVE_HOME/lib/hbase-hadoop-compat-1.3.1.jar
# CDH版本命令
export HBASE_HOME=/opt/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p0.8/lib/hbase
export HIVE_HOME=/opt/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p0.8/lib/hive
ln -s $HBASE_HOME/lib/hbase-common-1.2.0-cdh5.16.2.jar $HIVE_HOME/lib/hbase-common-1.2.0-cdh5.16.2.jar
ln -s $HBASE_HOME/lib/hbase-server-1.2.0-cdh5.16.2.jar $HIVE_HOME/lib/hbase-server-1.2.0-cdh5.16.2.jar
ln -s $HBASE_HOME/lib/hbase-client-1.2.0-cdh5.16.2.jar $HIVE_HOME/lib/hbase-client-1.2.0-cdh5.16.2.jar
ln -s $HBASE_HOME/lib/hbase-protocol-1.2.0-cdh5.16.2.jar $HIVE_HOME/lib/hbase-protocol-1.2.0-cdh5.16.2.jar
ln -s $HBASE_HOME/lib/hbase-it-1.2.0-cdh5.16.2.jar $HIVE_HOME/lib/hbase-it-1.2.0-cdh5.16.2.jar
ln -s $HBASE_HOME/lib/htrace-core-3.2.0-incubating.jar $HIVE_HOME/lib/htrace-core-3.2.0-incubating.jar
ln -s $HBASE_HOME/lib/hbase-hadoop2-compat-1.2.0-cdh5.16.2.jar $HIVE_HOME/lib/hbase-hadoop2-compat-1.2.0-cdh5.16.2.jar
ln -s $HBASE_HOME/lib/hbase-hadoop-compat-1.2.0-cdh5.16.2.jar $HIVE_HOME/lib/hbase-hadoop-compat-1.2.0-cdh5.16.2.jar
同时在hive-site.xml中修改zookeeper的属性,如下:
<property>
<name>hive.zookeeper.quorum</name>
<value>cm1.cdh.com,cm3.cdh.com,cm2.cdh.com</value>
<description>The list of ZooKeeper servers to talk to. This is only needed for read/write locks.</description>
</property>
<property>
<name>hive.zookeeper.client.port</name>
<value>2181</value>
<description>The port of ZooKeeper servers to talk to. This is only needed for read/write locks.</description>
</property>
2.案例一
目标:建立Hive表,关联HBase表,插入数据到Hive表的同时能够影响HBase表。
分步实现:
-
在Hive中创建表同时关联HBase
CREATE TABLE hive_hbase_emp_table( empno int, ename string) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ("hbase.columns.mapping" = " :key, info:ename ") TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");
hbase.columns.mapping
是必须的,这将会和 HBase 表的列族进行验证。hbase.table.name
属性是可选的,默认指定 HBase 表名与 Hive 表名一致。
提示:完成之后,可以分别进入Hive和HBase查看,都生成了对应的表
hbase(main):001:0> list TABLE hbase_emp_table 1 row(s) in 0.1940 seconds hive> show tables; OK hive_hbase_emp_table Time taken: 0.017 seconds, Fetched: 1 row(s)
-
在Hive中创建临时中间表,用于load文件中的数据
提示:不能将数据直接load进Hive所关联HBase的那张表中
CREATE TABLE emp( empno int, ename string) row format delimited fields terminated by '\t';
-
向Hive中间表中load数据
[root@cm1 data]# vi emp.txt 1 zhangsan 2 lisi 3 wangwu hive> load data local inpath '/root/data/emp.txt' into table emp;
-
通过insert命令将中间表中的数据导入到Hive关联HBase的那张表中
hive> insert into table hive_hbase_emp_table select * from emp;
-
查看Hive以及关联的HBase表中是否已经成功的同步插入了数据
Hive:
hive> select * from hive_hbase_emp_table; OK 1 zhangsan 2 lisi 3 wangwu Time taken: 0.108 seconds, Fetched: 3 row(s)
HBase:
hbase(main):003:0> scan 'hbase_emp_table' ROW COLUMN+CELL 1 column=info:ename, timestamp=1574497228455, value=zhangsan 2 column=info:ename, timestamp=1574497228455, value=lisi 3 column=info:ename, timestamp=1574497228455, value=wangwu 3 row(s) in 0.0460 seconds
-
此时在HBase中插入数据后,Hive中也可以查到了
hbase(main):004:0> put 'hbase_emp_table','4','info:ename','zhaoliu' 0 row(s) in 0.0650 seconds hive> select * from hive_hbase_emp_table; OK 1 zhangsan 2 lisi 3 wangwu 4 zhaoliu Time taken: 0.096 seconds, Fetched: 4 row(s)
3.案例二
目标:在HBase中已经存储了某一张表hbase_emp_table,然后在Hive中创建一个外部表来关联HBase中的hbase_emp_table这张表,使之可以借助Hive来分析HBase这张表中的数据。
注:该案例2紧跟案例1的脚步,所以完成此案例前,请先完成案例1。
注意:如果HBase中的表已经存在,此时hive想与其做关联,需要使用外部表才可成功
分步实现:
-
在Hive中创建外部表
CREATE EXTERNAL TABLE relevance_hbase_emp( empno int, ename string) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ("hbase.columns.mapping" = " :key, info:ename ") TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");
-
关联后就可以使用Hive函数进行一些分析操作了
hive> select * from relevance_hbase_emp; OK 1 zhangsan 2 lisi 3 wangwu 4 zhaoliu Time taken: 0.104 seconds, Fetched: 4 row(s)
四,总结
- 使用 hive-hbase-handler-xxx.jar 包实现 Hive 与 HBase 关联,要注意hive和hbase兼容性。
- Hive 读取的是 HBase 表最新的数据。
- 通过 Hive 创建的 HBase 表的值默认只有一个 VERSION ,可之后再修改 HBase 表值的最大 VERSION 数。
- Hive 只显示与 HBase 对应的列值,而那些没有对应的 HBase 列在 Hive 表中不显示。
- Hive 表与 HBase 表关联后,数据可以在 Hive 端插入,也可在 HBase 中插入。
- 创建 Hive 外部表与 HBase 的关联,可实现将 Hive 数据导入到 HBase 中。该方式是利用两者本身对外的 API 接口互相通信来完成的,在数据量不大(4T以下)的情况下可以选择该方式导入数据。
- 如果HBase中的表已经存在,此时hive想与其做关联,需要使用外部表才可成功