http://blog.csdn.net/vah101/article/details/22597341

这篇文章最初是基于介绍HIVE-705。这个功能允许Hive QL命令访问HBase表,进行读(select)、写(insert)操作。它甚至可以基于join、union操作对hbase表和hive原生的表进行混合访问。

这个功能还在不断的完善中,欢迎提出建议。

存储handler

在开始介绍之前,首先请阅读StorageHandlers,对存储处理程序的框架有个初步的认识,可以帮助读者理解HBase集成。

使用方法

这个存储处理程序被编译成一个独立的模块, hive-hbase-handler-x.y.z.jar,必须与guava、zookeeper的jar包被hive的客户端程序识别到(通过--auxpath指定)。也需要正确的配置hbase master的ip地址,保证能够与hbase连接。启动HBase集群的方法,请见the HBase documentation

这里有个例子是使用源代码编译环境的命令行,连接到一个单结点的HBase server。(注意,jar包的位置在hive 0.9.0版本以后发生了变化,对于早期的版本,要注意这些变化)

$HIVE_SRC/build/dist/bin/hive --auxpath $HIVE_SRC/build/dist/lib/hive-hbase-handler-0.9.0.jar,$HIVE_SRC/build/dist/lib/hbase-0.92.0.jar,$HIVE_SRC/build/dist/lib/zookeeper-3.3.4.jar,$HIVE_SRC/build/dist/lib/guava-r09.jar -hiveconf hbase.master=hbase.yoyodyne.com:60000

以下则是一个连接到一个分布式的HBase集群的例子,通过一个3结点的zookeeper集群来确定HBase的master结点:

$HIVE_SRC/build/dist/bin/hive --auxpath $HIVE_SRC/build/dist/lib/hive-hbase-handler-0.9.0.jar,$HIVE_SRC/build/dist/lib/hbase-0.92.0.jar,$HIVE_SRC/build/dist/lib/zookeeper-3.3.4.jar,$HIVE_SRC/build/dist/lib/guava-r09.jar -hiveconf hbase.zookeeper.quorum=zk1.yoyodyne.com,zk2.yoyodyne.com,zk3.yoyodyne.com

这个处理程序需要Hadoop 0.20版本以上,当前只测试过基于hadoop-0.20.x、hbase-0.92.0和zookeeper-3.3.4的情况。如果你不是使用hbase-0.92.0,你将需要重新编译与hbase的jar包相对应的handler处理程序,并且修改上文中提到的相应的--auxpath命令行参数。使用不对应的hbase jar包编译,将会导致连接错误异常,比如 MasterNotRunningException,这是因为hbase的RPC协议经常随版本更新发生变化。

为了创建一个新的可供hive管理的HBase表,需要使用“ STORED BY clause on CREATE TABLE”命令:

[python] view plaincopy
  1. CREATE TABLE hbase_table_1(key int, value string)
  2. STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
  3. WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf1:val")
  4. TBLPROPERTIES ("hbase.table.name" = "xyz");

这个hbase.columns.mapping属性是必需的,将会被下一段的所解释。hbase.table.name属性是可选的,它控制了HBase中创建的表的名字,并且允许其与hive表使用不同的名字。在这个例子中欧,在hive中的表名是hbase_table_1,在HBase中,则被命名为xyz。如果没有特别标名,hive与hbase表将会使用相同的名字。

在以上命令执行之后,我们就能通过HBase的shell看到一个新的空表:

[python] view plaincopy
  1. $ hbase shell
  2. HBase Shell; enter 'help<RETURN>' for list of supported commands.
  3. Version: 0.20.3, r902334, Mon Jan 25 13:13:08 PST 2010
  4. hbase(main):001:0> list
  5. xyz
  6. 1 row(s) in 0.0530 seconds
  7. hbase(main):002:0> describe "xyz"
  8. DESCRIPTION                                                             ENABLED
  9. {NAME => 'xyz', FAMILIES => [{NAME => 'cf1', COMPRESSION => 'NONE', VE true
  10. RSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY =>
  11. 'false', BLOCKCACHE => 'true'}]}
  12. 1 row(s) in 0.0220 seconds
  13. hbase(main):003:0> scan "xyz"
  14. ROW                          COLUMN+CELL
  15. 0 row(s) in 0.0060 seconds

注意,即使在映射中配置了“val”这个列名,但是在hbase shell输出的描述中,只能看到列族(column family)的名字“cf1”。这是因为在HBase中,只有列族(而不是列)的名字会被保存在表级的元数据中;列族中的列名只能保存在底层的列数据中。

这里将介绍如何将数据从Hive中转移到HBase的表中(如果创建一个示例表pokes,可以参考GettingStarted):

[python] view plaincopy
  1. INSERT OVERWRITE TABLE hbase_table_1 SELECT * FROM pokes WHERE foo=98;

使用HBase shell来验证一下数据是否被加载:

[python] view plaincopy
  1. hbase(main):009:0> scan "xyz"
  2. ROW                          COLUMN+CELL
  3. 98                          column=cf1:val, timestamp=1267737987733, value=val_98
  4. 1 row(s) in 0.0110 seconds

通过hive进行检索的结果是:

[python] view plaincopy
  1. hive> select * from hbase_table_1;
  2. Total MapReduce jobs = 1
  3. Launching Job 1 out of 1
  4. ...
  5. OK
  6. 98  val_98
  7. Time taken: 4.582 seconds

Inserting large amounts of data may be slow due to WAL overhead; if you would like to disable this, make sure you have HIVE-1383 (as of Hive 0.6), and then issue this command before the INSERT:

插入大量的数据将会因为WAL机制导致速度缓慢;如果想禁用该功能,要确保已经打过HIVE-1383(针对hive 0.6),然后在插入数据之前,执行以下命令:

[python] view plaincopy
  1. set hive.hbase.wal.enabled=false;

警告: 禁用WAL功能将会导致HBase在异常出错时丢失数据,所以只能在还有其他恢复手段的时候使用这个功能。

如果你想让hive访问HBase上已经存在的表,可以使用创建外表功能“CREATE EXTERNAL TABLE”:

[python] view plaincopy
  1. CREATE EXTERNAL TABLE hbase_table_2(key int, value string)
  2. STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
  3. WITH SERDEPROPERTIES ("hbase.columns.mapping" = "cf1:val")
  4. TBLPROPERTIES("hbase.table.name" = "some_existing_table");

hbase.columns.mapping仍然是必需的,而且要保证它与HBase表上现有的列族相对应。hbase.table.name是可选项。

列的映射

这里有两种SERDEPROPERTIES,将会对HBase列映射到hive产生影响:

  • hbase.columns.mapping
  • hbase.table.default.storage.tepy:  它可以被设置为“string”(默认值)或者binary,这个选项只在hive0.9版本以后才可用,因为之前的版本只支持string。

当前可用的列映射配置方法多少有些繁琐:

  • 对于每个hive列,表的创建者必须在hbase.columns.mapping字符串中,指定一系列相对应逗号分隔的映射项(有多少个hive列,就必须有多少个映射项与之相对于),注意空格不能用来表示entry,因为空格会被解释成列名的一部分。
  • 一个映射项必须为如下的形式:key或者列族名:[列名][#(二进制|字符串) (通过#的方式指定该映射项在HBase中以二进制数的形式保存,在hive 0.9.0版本之前,没有此功能)
    • 如果没有特别指定,则使用hbase.table.default.storage.type
    • Any prefixes of the valid values are valid too (i.e. #b instead of #binary)
    • 如果你指定一个列为二进制,则在HBase相应的单元格中以HBase的bytes类来保存相应的数值
  • 必须指定一个:key映射,当前还不支持复合主键
  • (注意在0.6版本的HIVE-1228之前,:key还不被支持,第一个hive列会隐式的被作为主键(rowkey);在Hive 0.6版本以后,强烈的推荐用户明确的指定作为rowkey的列;未来有可能会不再支持隐式主键的方式)
  • if no column-name is given, then the Hive column will map to all columns in the corresponding HBase column family, and the Hive MAP datatype must be used to allow access to these (possibly sparse) columns
  • 当前还没有方法能够读取HBase中的时间戳属性,查询中只能读取最新时间戳对应的数据
  • 因为HBase没有在列中给出数据类型的信息,所以序列化/反序列化模块先将其转换为字符串再存储到HBase中;现在还没有方法对每个列加入一个用户自定的序列化/反序列化模块。
  • 并不需要引用HBase中的每个列族,但是这会导致Hive表无法访问到HBase中的这个列;可以将多个Hive表映射到一个HBase表中

下面几段将会通过一个具体的例子来介绍当前可以使用的几种映射方式:

多个列和列族

这里有个例子是三个hive列映射到两个HBase的列族,两个Hive列(value1、value2)对应一个列族(a,其中两个HBase列名为b、c),另一个Hive列则对应一个列族(d)中的单独的列(e)

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

在hive中查看表结构,结果如下所示:

[plain] view plaincopy
  1. hbase(main):014:0> describe "hbase_table_1"
  2. DESCRIPTION                                                             ENABLED
  3. {NAME => 'hbase_table_1', FAMILIES => [{NAME => 'a', COMPRESSION => 'N true
  4. ONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_M
  5. EMORY => 'false', BLOCKCACHE => 'true'}, {NAME => 'd', COMPRESSION =>
  6. 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN
  7. _MEMORY => 'false', BLOCKCACHE => 'true'}]}
  8. 1 row(s) in 0.0170 seconds
  9. hbase(main):015:0> scan "hbase_table_1"
  10. ROW                          COLUMN+CELL
  11. 100                         column=a:b, timestamp=1267740457648, value=val_100
  12. 100                         column=a:c, timestamp=1267740457648, value=101
  13. 100                         column=d:e, timestamp=1267740457648, value=102
  14. 98                          column=a:b, timestamp=1267740457648, value=val_98
  15. 98                          column=a:c, timestamp=1267740457648, value=99
  16. 98                          column=d:e, timestamp=1267740457648, value=100
  17. 2 row(s) in 0.0240 seconds

在hive中检索的结果为:

[plain] view plaincopy
  1. hive> select * from hbase_table_1;
  2. Total MapReduce jobs = 1
  3. Launching Job 1 out of 1
  4. ...
  5. OK
  6. 100 val_100 101 102
  7. 98  val_98  99  100
  8. Time taken: 4.054 seconds

Hive使用MAP类型映射整个列族

这里,举一个Hive使用MAP类型来读取这个column family的例子。每行包含不同的列,列的命名根据map中的key,列的值为map中的value:

[plain] view plaincopy
  1. CREATE TABLE hbase_table_1(value map<string,int>, row_key int)
  2. STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
  3. WITH SERDEPROPERTIES (
  4. "hbase.columns.mapping" = "cf:,:key"
  5. );
  6. INSERT OVERWRITE TABLE hbase_table_1 SELECT map(bar, foo), foo FROM pokes
  7. WHERE foo=98 OR foo=100;

这个例子同时也验证了hive使用的第一个列不一定是rowkey所在的列

这个表在HBase中看起来是这样的:

[plain] view plaincopy
  1. hbase(main):012:0> scan "hbase_table_1"
  2. ROW                          COLUMN+CELL
  3. 100                         column=cf:val_100, timestamp=1267739509194, value=100
  4. 98                          column=cf:val_98, timestamp=1267739509194, value=98
  5. 2 row(s) in 0.0080 seconds

在hive中进行检索,结果如下:

[plain] view plaincopy
  1. hive> select * from hbase_table_1;
  2. Total MapReduce jobs = 1
  3. Launching Job 1 out of 1
  4. ...
  5. OK
  6. {"val_100":100} 100
  7. {"val_98":98}   98
  8. Time taken: 3.808 seconds

注意,MAP类型中key必须是字符串,因为它将用来为HBase列命名,所以如下的表定义方式将会出错:

[plain] view plaincopy
  1. CREATE TABLE hbase_table_1(key int, value map<int,int>)
  2. STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
  3. WITH SERDEPROPERTIES (
  4. "hbase.columns.mapping" = ":key,cf:"
  5. );
  6. FAILED: Error in metadata: java.lang.RuntimeException: MetaException(message:org.apache.hadoop.hive.serde2.SerDeException org.apache.hadoop.hive.hbase.HBaseSerDe: hbase column family 'cf:' should be mapped to map<string,?> but is mapped to map<int,int>)

违反规则的映射方式:

如下的表定义方式不合乎规则,因为只有MAP方式可以把一个hive列映射到整个列族:

[plain] view plaincopy
  1. CREATE TABLE hbase_table_1(key int, value string)
  2. STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
  3. WITH SERDEPROPERTIES (
  4. "hbase.columns.mapping" = ":key,cf:"
  5. );
  6. FAILED: Error in metadata: java.lang.RuntimeException: MetaException(message:org.apache.hadoop.hive.serde2.SerDeException org.apache.hadoop.hive.hbase.HBaseSerDe: hbase column family 'cf:' should be mapped to map<string,?> but is mapped to string)

使用二进制列的例子:

依赖默认的hbase.table.default.storage.type:

[plain] view plaincopy
  1. CREATE TABLE hbase_table_1 (key int, value string, foobar double)
  2. STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
  3. WITH SERDEPROPERTIES (
  4. "hbase.columns.mapping" = ":key#b,cf:val,cf:foo#b"
  5. );

特别指定hbase.table.default.storage.type为二进制:

[plain] view plaincopy
  1. CREATE TABLE hbase_table_1 (key int, value string, foobar double)
  2. STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
  3. WITH SERDEPROPERTIES (
  4. "hbase.columns.mapping" = ":key,cf:val#s,cf:foo",
  5. "hbase.table.default.storage.type" = "binary"
  6. );

hive与hbase集成的更多相关文章

  1. 新闻实时分析系统Hive与HBase集成进行数据分析

    (一)Hive 概述 (二)Hive在Hadoop生态圈中的位置 (三)Hive 架构设计 (四)Hive 的优点及应用场景 (五)Hive 的下载和安装部署 1.Hive 下载 Apache版本的H ...

  2. 新闻网大数据实时分析可视化系统项目——12、Hive与HBase集成进行数据分析

    (一)Hive 概述 (二)Hive在Hadoop生态圈中的位置 (三)Hive 架构设计 (四)Hive 的优点及应用场景 (五)Hive 的下载和安装部署 1.Hive 下载 Apache版本的H ...

  3. 新闻实时分析系统Hive与HBase集成进行数据分析 Cloudera HUE大数据可视化分析

    1.Hue 概述及版本下载 1)概述 Hue是一个开源的Apache Hadoop UI系统,最早是由Cloudera Desktop演化而来,由Cloudera贡献给开源社区,它是基于Python ...

  4. Hive与HBase集成进行数据分析

    我们把hive的安装包上传的节点3来 解压 现在我们还是老规矩通过notopad++来连接我们的虚拟机来配置文件,把下面这两个文件重命名一下 修改这个文件 对hive-env.sh我们修改这里 下面我 ...

  5. 集成Hive和HBase

    1. MapReduce 用MapReduce将数据从本地文件系统导入到HBase的表中, 比如从HBase中读取一些原始数据后使用MapReduce做数据分析. 结合计算型框架进行计算统计查看HBa ...

  6. Hive On HBase实战

    1.概述 HBase是一款非关系型.分布式的KV存储数据库.用来存储海量的数据,用于键值对操作.目前HBase是原生是不包含SQL操作,虽然说Apache Phoenix可以用来操作HBase表,但是 ...

  7. 全网最详细的hive-site.xml配置文件里如何添加达到Hive与HBase的集成,即Hive通过这些参数去连接HBase(图文详解)

    不多说,直接上干货! 一般,普通的情况是 全网最详细的hive-site.xml配置文件里添加<name>hive.cli.print.header</name>和<na ...

  8. 3.12-3.16 Hbase集成hive、sqoop、hue

    一.Hbase集成hive https://cwiki.apache.org/confluence/display/Hive/HBaseIntegration 1.说明 Hive与HBase整合在一起 ...

  9. hive和hbase整合的原因和原理

    为什么要进行hive和hbase的整合? hive是高延迟.结构化和面向分析的: hbase是低延迟.非结构化和面向编程的. Hive集成Hbase就是为了使用hbase的一些特性.或者说是中和它们的 ...

随机推荐

  1. Linux shell 常用

    使用Linux shell是我每天的基本工作,但我经常会忘记一些有用的shell命令和l技巧.当然,命令我能记住,但我不敢说能记得如何用它执行某个特定任务.于是,我开始在一个文本文件里记录这些用法,并 ...

  2. hdu 5533 Dancing Stars on Me

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5533 Dancing Stars on Me Time Limit: 2000/1000 MS (Ja ...

  3. jquery完成带复选框的表格行高亮显示

    jquery完成带复选框的表格行高亮显示 通过jquery技术来操作表格是件简单的事,通过jquery的语法,可以很轻松的完成表格的隔行换色,悬浮高亮,在实际的应用中可能会出现表格中带复选框的,删除时 ...

  4. 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...

  5. yii2 i18n学习

    举例说明常见的翻译:Yii::t('app','Login'):追踪源码:BaseYii.php 文件 ,Yii::t($category, $message, $params = [], $lang ...

  6. 【44】将与参数无关的代码抽离templates

    1.template是产生代码的代码,这就意味着源码看起来很少,生成的目标码大量膨胀. 2.考虑,如果两个方法有重复代码,我们会新建一个方法,把重复的代码放进去,原先两个方法调用第三个方法.如果两个类 ...

  7. 【39】明智而审慎第使用private继承

    1.private继承意味着,根据某物实现出,继承父类的实现,关闭父类的接口,并不是Is-A的关系,不满足里氏代换,继承的内容访问权限都修改为private. 2.那么问题来了,复合也表达根据某物实现 ...

  8. MmSystem播放Wav格式声音

    //MmSystem播放Wav格式声音 //MmSystem 支持 *.wav声音格式 snd ->SoundRecorderuses MmSystem; //引用MmSystem//播放系统声 ...

  9. Nginx+Keepalived+Tomcat之动静分离的web集群

    #vi /etc/nginx/nginx.conf############################################user nginx nginx;worker_process ...

  10. Android使用的开发MediaRecorder录制视频

    MediaRecorder除了使用录制音频.还可用于录制视频.关于MediaRecorder的具体解释大家能够參考<Android开发之MediaRecorder类具体解释>.使用Medi ...