@ 2016-05-30
环境说明
- CentOS 6.7
- Hadoop 2.7.2
- Hive 2.0.0
- HBase 1.1.3
有两种方式向Hive的类路径添加jar包:
hive.aux.jars.path
/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
The location of the plugin jars that contain implementations of user defined functions and serdes.
add jar /opt/hive-2.0.0/lib/hive-hbase-handler-2.0.0.jar;
add jar ......
hive在执行命令前会先读取.hiverc的文件中的内容
启动Hive 和 HBase即可使用,具体示例如第3节。
插入大量数据可能会由于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中对应的表。
控制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中的列名
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)
如何使用Hive的Map数据类型访问列族,每行可以有很多不同的列,而列名正好对应到Map类型字段的Keys,而列值正好对应到Map类型字段的Map值。Hive建表SQL如下:
CREATE TABLE hbase_table_3(value map, 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)
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,可以找到是哪个包缺失了,加上之后测试即可。