原创干货 | Hive与HBase的集成实践
Posted 天善大数据
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原创干货 | Hive与HBase的集成实践相关的知识,希望对你有一定的参考价值。
Hive与HBase集成实践
大数据平台搭建
hive-2.0.0
hbase 1.1.3
环境说明
CentOS 6.7
Hadoop 2.7.2
Hive 2.0.0
HBase 1.1.3
一、具体步骤
1. 拷贝jar包
首先删除$HIVE_HOME/lib下HBase和ZooKeeper相关的jar包
然后重新拷贝$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/hbase-1.1.3/lib/htrace-core-3.1.0-incubating.jar;
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;
add jar /opt/hive-2.0.0/lib/hive-metastore-2.0.0.jar;
add jar /opt/hbase-1.1.3/lib/hbase-server-1.1.3.jar;
add jar /opt/hbase-1.1.3/lib/hbase-client-1.1.3.jar;
add jar /opt/hbase-1.1.3/lib/hbase-protocol-1.1.3.jar;
add jar /opt/hive-2.0.0/hcatalog/share/hcatalog/hive-hcatalog-core-2.0.0.jar;
add jar /opt/hive-2.0.0/lib/datanucleus-core-4.1.6.jar;
add jar /opt/hive-2.0.0/lib/datanucleus-api-jdo-4.2.1.jar;
add jar /opt/hive-2.0.0/lib/datanucleus-rdbms-4.1.7.jar;
add jar /opt/hive-2.0.0/lib/hive-cli-2.0.0.jar;
add jar /opt/hive-2.0.0/lib/hive-hbase-handler-2.0.0.jar;
hive在执行命令前会先读取.hiverc的文件中的内容
启动Hive 和 HBase即可使用,具体示例如第3节。
二、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中的列名
三、 示例
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)
火爆参团:天善学院联合Mars老师推出《对话大数据系列技术 从破冰到精进》正在火热参团中,已是冰点价了喔~
参团方式:扫描二维码 | 阅读原文
以上是关于原创干货 | Hive与HBase的集成实践的主要内容,如果未能解决你的问题,请参考以下文章
全网最详细的hive-site.xml配置文件里如何添加达到Hive与HBase的集成,即Hive通过这些参数去连接HBase(图文详解)