Hive与HBase集成实践

@ 2016-05-30

环境说明

  • CentOS 6.7
  • Hadoop 2.7.2
  • Hive 2.0.0
  • HBase 1.1.3

1. 具体步骤

1. 拷贝jar包
  1. 首先删除$HIVE_HOME/lib下HBase和ZooKeeper相关的jar包
  2. 然后重新拷贝$HBASE_HOME/lib下的HBase和ZooKeeper相关的jar包至Hive下
2. 在Hive的类路径中添加一些这些jar包

有两种方式向Hive的类路径添加jar包:

  • 修改hive-site.xml中hive.aux.jars.path的值
<property>
    <name>hive.aux.jars.path</name>
    <value>/opt/hive-2.0.0/lib/guava-14.0.1.jar,/opt/hive-2.0.0/lib/zookeeper-3.4.6.jar,/opt/hive-2.0.0/lib/hive-hbase-handler-2.0.0.jar,/opt/hive-2.0.0/lib/hbase-common-1.1.3.jar,/opt/hive-2.0.0/lib/hbase-server-1.1.3.jar</value>
    <description>The location of the plugin jars that contain implementations of user defined functions and serdes.</description>
  </property>
  • 在$HIVE_HOME/conf/下新建.hiverc文件,加入类似下列语句
add jar /opt/hive-2.0.0/lib/hive-hbase-handler-2.0.0.jar;
add jar ......

hive在执行命令前会先读取.hiverc的文件中的内容

启动Hive 和 HBase即可使用,具体示例如第3节。

2. Hive集成HBase的原理

1. Storage Handler
  • 基本原理
    Hive与HBase集成的实现是利用了这两者本身对外提供的API进行相互通信,这种相互通信是通过$HIVE_HOME/lib/hive-hbase-handler-2.0.0.jar工具类实现的。通过HBaseStorageHandler,Hive可以获取到Hive表所对应的HBase表名,列簇和列,InputFormat、OutputFormat类,创建和删除HBase表等。
  • 访问
    Hive访问HBase中HTable的数据,实质上是通过MR读取HBase的数据,而MR是使用HiveHBaseTableInputFormat完成对表的切分,获取RecordReader对象来读取数据的。
    对HBase表的切分原则是一个Region切分成一个Split,即表中有多少个Regions,MR中就有多少个Map;
    读取HBase表数据都是通过构建Scanner,对表进行全表扫描,如果有过滤条件,则转化为Filter。当过滤条件为rowkey时,则转化为对rowkey的过滤;Scanner通过RPC调用RegionServer的next()来获取数据。
2. 使用

插入大量数据可能会由于WAL负载导致速度很慢,可以通过在插入数据之前做如下设置:

set hive.hbase.wal.enabled=false;

但是关闭WAL可能会使HBase发生错误时出现数据丢失,所以建议只有在你已有其他数据恢复策略时才使用这种设置。

若想使Hive可以访问已存在的HBase表,可以使用下面的语句创建这样的Hive表:

CREATE EXTERNAL TABLE hbase_table_2(key int, value string) 
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = "cf1:val")
TBLPROPERTIES("hbase.table.name" = "xyz", "hbase.mapred.output.outputtable" = "xyz");

hbase.columns.mapping是必须的,这将会和已存在的HBase表的列族进行验证,而hbase.table.name和hbase.mapred.output.outputtable是可选的。当在Hive中删除此表时,并不影响HBase中对应的表。

3. 字段映射

控制HBase字段和Hive之间的映射有两种SERDEPROPERTIES:
- hbase.columns.mapping
- hbase.table.default.storage.type,可以是string(default)或binary中的任一个,指定这个选项只有在Hive 0.9之后可使用.

目前所支持的字段映射多少是有些难处理或存在约束的:
- 对于每一个Hive字段,表的创建者必须用逗号分隔的字符串(hbase.columns.mapping)指定对应的入口(Hive表有n个字段,则该字符串得指定n个入口),在各个入口之间不能由空格(因为空格会被解析成字段名中的一部分)。
- 映射入口必须是以下两者之一:行健或’列族名:[列名][#(binary|string)]’
- 如果没有指定类型,则直接使用hbase.table.default.storage.type的值
- 合法值的的前缀也是合法的(例如#b表示#binary)
- 如果指定某字段为binary,则对应的HBase中的单元格则应该是HBase的Bytes类的内容组成
- 必须要有确切的行健映射
- 如果没有指定列名,则默认使用Hive的字段名作为HBase中的列名

3. 示例

1. 多列和列族

Hive表中的3个字段与HBase中的2个列族,其中2个Hive字段(value1和value2)对应到1个HBase列族(列族a,列b和c),另1个Hive字段(e)对应到另1个HBase列族的单个列(d)。Hive建表SQL如下:

CREATE TABLE hbase_table_1(key int, value1 string, value2 int, value3 int) 
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
"hbase.columns.mapping" = ":key,a:b,a:c,d:e"
);
INSERT OVERWRITE TABLE hbase_table_1 SELECT foo, bar, foo+1, foo+2 
FROM pokes WHERE foo=98 OR foo=100;

此表在HBase中是这个样子的:

hbase(main):006:0> describe 'hive_hbase.hbase_table_2'
Table hive_hbase.hbase_table_2 is ENABLED                                   
hive_hbase.hbase_table_2                                                    
COLUMN FAMILIES DESCRIPTION                                                 
{NAME => 'a', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', K
EEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER
', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSI
ZE => '65536', REPLICATION_SCOPE => '0'}                                    
{NAME => 'd', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', K
EEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER
', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSI
ZE => '65536', REPLICATION_SCOPE => '0'}                                    
2 row(s) in 0.0190 seconds

hbase(main):007:0> scan'hive_hbase.hbase_table_2'
ROW                  COLUMN+CELL                                            
 100                 column=a:b, timestamp=1464598569847, value=val_100     
 100                 column=a:c, timestamp=1464598569847, value=101         
 100                 column=d:e, timestamp=1464598569847, value=102         
 98                  column=a:b, timestamp=1464598569847, value=val_98      
 98                  column=a:c, timestamp=1464598569847, value=99          
 98                  column=d:e, timestamp=1464598569847, value=100         
2 row(s) in 0.0200 seconds

再回到Hive中查询此表:

hive> select * from hbase_table_2;
OK
100 val_100 101 102
98  val_98  99  100
Time taken: 0.298 seconds, Fetched: 2 row(s)
2. Hive的Map字段与HBase列族

如何使用Hive的Map数据类型访问列族,每行可以有很多不同的列,而列名正好对应到Map类型字段的Keys,而列值正好对应到Map类型字段的Map值。Hive建表SQL如下:

CREATE TABLE hbase_table_3(value map<string,int>, row_key int) 
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
"hbase.columns.mapping" = "cf:,:key"
);
INSERT OVERWRITE TABLE hbase_table_3 SELECT map(bar, foo), foo FROM pokes 
WHERE foo=98 OR foo=100;

这个表在HBase中是长这个样子:

hbase(main):009:0> scan'hive_hbase.hbase_table_3'
ROW                  COLUMN+CELL                                            
 100                 column=cf:val_100, timestamp=1464600230691, value=100  
 98                  column=cf:val_98, timestamp=1464600230691, value=98    
2 row(s) in 0.0220 seconds

再回到Hive中查询此表:

hive> select * from hbase_table_3;
OK
{"val_100":100} 100
{"val_98":98}   98
Time taken: 0.163 seconds, Fetched: 2 row(s)

4. 问题汇总

1. 向集成表中插入数据时报错
Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.hbase.io.ImmutableBytesWritable

原因:hive的类路径中缺少hbae-common和hbase-hadoop2-compact两个包
解决:在$HIVE_HOME/conf/.hiverc中加入下面两行

add jar /opt/hbase-1.1.3/lib/hbase-common-1.1.3.jar;
add jar /opt/hbase-1.1.3/lib/hbase-hadoop2-compat-1.1.3.jar;

当出现ClassNotFoundException时,首先考虑类路径缺失,查看日志找到Caused By,可以找到是哪个包缺失了,加上之后测试即可。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值