Hive HBase 集成
Hive HBase集成Avro 数据存储在 HBase 列中介绍用法列映射多个列和列簇Hive MAP 到 HBase 列族Hive MAP 到 HBase 列前缀隐藏列前缀非法:Hive 原语到 HBase 列族二进制列示例简单的复合行键(As of Hive 0.13.0)复杂的复合行键和 HBaseKeyFactoryAvro 数据存储在 HBase 列中(As of Hive 0.14.
Hive HBase集成
Avro 数据存储在 HBase 列中
版本信息:
Avro 数据存储在 HBase 列中 从 Hive 0.9.0 开始,HBase 集成至少需要 HBase 0.92, 早期版本的 Hive 使用 HBase 0.89/0.90。
Hive 1.x 将与 HBase 0.98.x 及更低版本保持兼容。 Hive 2.x 将与 HBase 1.x 及更高版本兼容。(有关详细信息,请参阅 HIVE-10990。) 想要使用 Hive 1.x 使用 HBase 1.x 的消费者需要自己编译 Hive 1.x 流代码。
介绍
此文章记录了最初在 HIVE-705 中引入的 Hive/HBase 集成支持。此功能允许 Hive QL 语句访问 HBase 表以进行读取 (SELECT) 和写入 (INSERT)。甚至可以通过连接和联合将 HBase 表的访问与本机 Hive 表相结合。
用法
存储处理程序构建为独立模块 hive-hbase-handler-x.y.z.jar,它必须在 Hive 客户端辅助路径以及 HBase、Guava 和 ZooKeeper jar 上可用。它还需要设置正确的配置属性才能连接到正确的 HBase 主服务器。
-
这是一个在源构建环境中使用 CLI 的示例,目标是单节点 HBase 服务器。 (请注意,Hive 0.9.0 中的 jar 位置和名称已更改,因此对于早期版本,需要进行一些更改。)
$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 主节点:
$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 重建处理程序,并相应地更改上面的 --auxpath 。不使用匹配版本会导致误导性的连接失败,例如 MasterNotRunningException,因为 HBase RPC 协议经常变化。
为了创建一个由 Hive 管理的新 HBase 表,请在 CREATE TABLE 上使用 STORED BY 子句:
CREATE TABLE hbase_table_1(key int, value string) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,cf1:val") TBLPROPERTIES ("hbase.table.name" = "xyz", "hbase.mapred.output.outputtable" = "xyz"); -
hbase.columns.mapping 属性是必需的,将在下一节中解释。 hbase.table.name 属性是可选的;它控制 HBase 已知的表的名称,并允许 Hive 表具有不同的名称。在此示例中,该表在 Hive 中称为 hbase_table_1,在 HBase 中称为 xyz。如果未指定,则 Hive 和 HBase 表名称将相同。 hbase.mapred.output.outputtable 属性是可选的;如果您打算向表中插入数据,则需要它(该属性由 hbase.mapreduce.TableOutputFormat 使用)
执行上述命令后,您应该能够在 HBase shell 中看到新的(空)表:
$ hbase shell HBase Shell; enter 'help<RETURN>' for list of supported commands. Version: 0.20.3, r902334, Mon Jan 25 13:13:08 PST 2010 hbase(main):001:0> list xyz 1 row(s) in 0.0530 seconds hbase(main):002:0> describe "xyz" DESCRIPTION ENABLED {NAME => 'xyz', FAMILIES => [{NAME => 'cf1', COMPRESSION => 'NONE', VE true RSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'}]} 1 row(s) in 0.0220 seconds hbase(main):003:0> scan "xyz" ROW COLUMN+CELL 0 row(s) in 0.0060 seconds -
请注意,即使在映射中指定了列名“val”,HBase shell 的 DESCRIBE 输出中也只出现列族名称“cf1”。这是因为在 HBase 中,表级元数据中只有列族(而不是列)是已知的;列族中的列名仅出现在每行级别。
以下是如何将数据从 Hive 移动到 HBase 表中:
INSERT OVERWRITE TABLE hbase_table_1 SELECT * FROM pokes WHERE foo=98; -
使用 HBase shell 验证数据是否已实际加载:
hbase(main):009:0> scan "xyz" ROW COLUMN+CELL 98 column=cf1:val, timestamp=1267737987733, value=val_98 1 row(s) in 0.0110 seconds -
然后通过 Hive 查询:
hive> select * from hbase_table_1; Total MapReduce jobs = 1 Launching Job 1 out of 1 ... OK 98 val_98 Time taken: 4.582 seconds -
由于 WAL 开销,插入大量数据可能会很慢;如果您想禁用它,请确保您有 HIVE-1383(从 Hive 0.6 开始),然后在 INSERT 之前使用以下命令:
set hive.hbase.wal.enabled=false;警告:如果发生 HBase 故障,禁用 WAL 可能会导致数据丢失,因此仅当您有其他可用的恢复策略时才使用此选项。 -
如果要授予 Hive 访问现有 HBase 表的权限,请使用 CREATE EXTERNAL TABLE:
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" = "some_existing_table", "hbase.mapred.output.outputtable" = "some_existing_table"); -
同样, hbase.columns.mapping 是必需的(并将根据现有 HBase 表的列族进行验证),而 hbase.table.name 是可选的。 hbase.mapred.output.outputtable 是可选的。
列映射
有两个 SERDEPROPERTIES 控制 HBase 列到 Hive 的映射:
- hbase.columns.mapping
- hbase.table.default.storage.type: 可以具有字符串(默认值)或二进制值,此选项仅从 Hive 0.9 开始可用,并且字符串行为是早期版本中唯一可用的
当前可用的列映射支持有些繁琐和限制:
- 对于每个 Hive 列,表创建者必须在以逗号分隔的 hbase.columns.mapping 字符串中指定相应的条目(因此对于具有 n 列的 Hive 表,该字符串应具有 n 个条目);不应在条目之间使用空格,因为它们将作为列名的一部分进行解释,这几乎肯定不是您想要的。
- 映射条目必须是 :key, :timestamp 或 column-family-name:[column-name][#(binary|string)(以# 分隔的类型规范是在 Hive 0.9.0 中添加的,早期版本将所有内容解释为字符串)
- 如果没有指定类型,将使用 hbase.table.default.storage.type 中的值
- 有效值的任何前缀也是有效的(即#b 而不是#binary)
- 如果您将列指定为二进制,则相应 HBase 单元格中的字节应采用 HBase 的 Bytes 类产生的形式。
- 必须只有一个 :key 映射(这可以映射到字符串或结构列 - 请参阅简单复合键和复杂复合键)
- (请注意,在 Hive 0.6 中的 HIVE-1228 之前,不支持 :key,并且第一个 Hive 列隐式映射到键;从 Hive 0.6 开始,现在强烈建议您始终明确指定密钥;我们将在未来放弃对隐式键映射的支持)
- 如果没有给出 column-name,则 Hive 列将映射到相应 HBase 列族中的所有列,并且必须使用 Hive MAP 数据类型来允许访问这些(可能是稀疏的)列。
- 从 HBase 1.1 (HBASE-2828) 开始,有一种方法可以使用特殊的 :timestamp 映射来访问 HBase 时间戳属性。它需要是 bigint 或时间戳。
- 没有必要引用每个 HBase 列族,但那些没有映射的列族将无法通过 Hive 表访问;可以将多个 Hive 表映射到同一个 HBase 表 接下来的几节提供了当前可能的列映射类型的详细示例。
多个列和列簇
- 这是一个包含三个 Hive 列和两个 HBase 列族的示例,两个 Hive 列(value1 和 value2)对应于其中一个列族(a,具有 HBase 列名 b 和 c),另一个 Hive 列对应于其自己的列族 (d) 中的单个列 (e) )。
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):014:0> describe "hbase_table_1" DESCRIPTION ENABLED {NAME => 'hbase_table_1', FAMILIES => [{NAME => 'a', COMPRESSION => 'N true ONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN_M EMORY => 'false', BLOCKCACHE => 'true'}, {NAME => 'd', COMPRESSION => 'NONE', VERSIONS => '3', TTL => '2147483647', BLOCKSIZE => '65536', IN _MEMORY => 'false', BLOCKCACHE => 'true'}]} 1 row(s) in 0.0170 seconds hbase(main):015:0> scan "hbase_table_1" ROW COLUMN+CELL 100 column=a:b, timestamp=1267740457648, value=val_100 100 column=a:c, timestamp=1267740457648, value=101 100 column=d:e, timestamp=1267740457648, value=102 98 column=a:b, timestamp=1267740457648, value=val_98 98 column=a:c, timestamp=1267740457648, value=99 98 column=d:e, timestamp=1267740457648, value=100 2 row(s) in 0.0240 seconds - 当查询回 Hive 时:
hive> select * from hbase_table_1; Total MapReduce jobs = 1 Launching Job 1 out of 1 ... OK 100 val_100 101 102 98 val_98 99 100 Time taken: 4.054 seconds
- 这是 HBase 中的样子:
Hive MAP 到 HBase 列族
- 以下是如何使用 Hive MAP 数据类型访问整个列族。每行可以有一组不同的列,其中列名对应于映射键,列值对应于映射值。
CREATE TABLE hbase_table_1(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_1 SELECT map(bar, foo), foo FROM pokes WHERE foo=98 OR foo=100;- 这是在 HBase 中的样子(在不同的行中有不同的列名):
hbase(main):012:0> scan "hbase_table_1" ROW COLUMN+CELL 100 column=cf:val_100, timestamp=1267739509194, value=100 98 column=cf:val_98, timestamp=1267739509194, value=98 2 row(s) in 0.0080 seconds - 当查询回 Hive 时:
hive> select * from hbase_table_1; Total MapReduce jobs = 1 Launching Job 1 out of 1 ... OK {"val_100":100} 100 {"val_98":98} 98 Time taken: 3.808 seconds - 注意MAP的key必须有数据类型string,因为它是用来命名HBase列的,所以下面的表定义会失败:
CREATE TABLE hbase_table_1(key int, value map<int,int>) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = ":key,cf:" ); 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>)
- 这是在 HBase 中的样子(在不同的行中有不同的列名):
Hive MAP 到 HBase 列前缀
- 另请注意,从 Hive 0.12 开始,还可以使用通配符来检索列。例如,如果要检索 HBase 中以前缀“col_prefix”开头的所有列,则应使用如下查询:
CREATE TABLE hbase_table_1(value map<string,int>, row_key int) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = "cf:col_prefix.*,:key" ); - 但同样的限制也适用。也就是说,映射的键应该是一个字符串,因为它映射到 HBase 列名,并且值可以是您正在检索的值的类型。另一个限制是给定前缀下的所有值都应该是相同的类型。也就是说,它们都应该是“int”类型或“string”类型等等。
隐藏列前缀
- 从 Hive 1.3.0 开始,可以在选择查询结果中隐藏列前缀。有 SerDe 布尔属性 hbase.columns.mapping.prefix.hide(默认为 false),它定义前缀是否应该隐藏在 Hive 映射的键中:
CREATE TABLE hbase_table_1(tags map<string,int>, row_key string) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = "cf:tag_.*,:key", "hbase.columns.mapping.prefix.hide" = "true" ); - 然后“标签”列的值(从 hbase_table_1 中选择标签)将是:
"x" : 1 instead of: "tag_x" : 1
非法:Hive 原语到 HBase 列族
- 如下表定义是非法的,因为 映射到整个列族的 Hive 列必须具有 MAP 类型:
CREATE TABLE hbase_table_1(key int, value string) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = ":key,cf:" ); 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的默认值:
CREATE TABLE hbase_table_1 (key int, value string, foobar double) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = ":key#b,cf:val,cf:foo#b" ); - 指定 hbase.table.default.storage.type:
CREATE TABLE hbase_table_1 (key int, value string, foobar double) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = ":key,cf:val#s,cf:foo", "hbase.table.default.storage.type" = "binary" );
简单的复合行键(As of Hive 0.13.0)
- 通过将 HBase 行键映射到 Hive 结构,并使用 ROW FORMAT DELIMITED…COLLECTION ITEMS TERMINATED BY,Hive 可以读取和写入带分隔符的复合键到 HBase。例子:
-- Create a table with a composite row key consisting of two string fields, delimited by '~' CREATE EXTERNAL TABLE delimited_example(key struct<f1:string, f2:string>, value string) ROW FORMAT DELIMITED COLLECTION ITEMS TERMINATED BY '~' STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( 'hbase.columns.mapping'=':key,f:c1'); ```
复杂的复合行键和 HBaseKeyFactory
从带有 HIVE-6411 的 Hive 0.14.0 开始(0.13.0 也支持复杂的复合键
- 对于更复杂的用例,Hive 允许用户指定 HBaseKeyFactory,它定义键到 Hive 结构中字段的映射。这可以使用 SERDEPROPERTIES 选项中的属性“hbase.composite.key.factory”进行配置:
-- Parse a row key with 3 fixed width fields each of width 10 -- Example taken from: https://svn.apache.org/repos/asf/hive/trunk/hbase-handler/src/test/queries/positive/hbase_custom_key2.q CREATE TABLE hbase_ck_4(key struct<col1:string,col2:string,col3:string>, value string) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.table.name" = "hbase_custom2", "hbase.mapred.output.outputtable" = "hbase_custom2", "hbase.columns.mapping" = ":key,cf:string", "hbase.composite.key.factory"="org.apache.hadoop.hive.hbase.SampleHBaseKeyFactory2"); - “hbase.composite.key.factory”应该是实现 HBaseKeyFactory 的类的完全限定类名。有关同一包中的固定长度示例,请参阅 SampleHBaseKeyFactory2。此类必须在您的类路径上才能使上述示例正常工作。待办事项:将它们放置在可访问的地方;他们目前只在测试代码中。
Avro 数据存储在 HBase 列中(As of Hive 0.14.0)
- Hive 0.14.0 以后支持在 HBase 列中存储和查询 Avro 对象,方法是使它们作为 Hive 的结构可见。这允许 Hive 对可以深度结构化的 HBase 数据执行临时分析。在 0.14.0 之前,HBase Hive 集成仅支持查询列中的原始数据类型。
- 一个示例 HiveQL 语句,其中 test_col_fam 是列族,而 test_col 是列名:
CREATE EXTERNAL TABLE test_hbase_avro ROW FORMAT SERDE 'org.apache.hadoop.hive.hbase.HBaseSerDe' STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ( "hbase.columns.mapping" = ":key,test_col_fam:test_col", "test_col_fam.test_col.serialization.type" = "avro", "test_col_fam.test_col.avro.schema.url" = "hdfs://testcluster/tmp/schema.avsc") TBLPROPERTIES ( "hbase.table.name" = "hbase_avro_table", "hbase.mapred.output.outputtable" = "hbase_avro_table", "hbase.struct.autogenerate"="true"); - 需要注意的重要属性是以下三个:
"test_col_fam.test_col.serialization.type" = "avro"- 该属性告诉 Hive 给定列族下的给定列是一个 Avro 列,因此 Hive 需要对其进行相应的反序列化。
"test_col_fam.test_col.avro.schema.url" = "hdfs://testcluster/tmp/schema.avsc" - 使用此属性,您可以为将用于反序列化的列指定读取器架构的位置。这可以像这里提到的那样在 HDFS 上,或者使用类似“test_col_fam.test_col.avro.schema.literal”属性的内容提供。如果您有一个用于存储此架构的自定义存储,您可以编写 AvroSchemaRetriever 的自定义实现并使用“avro.schema.retriever 属性”使用“test_col_fam.test_col.avro.schema.retriever”之类的属性将其插入。您需要确保具有此自定义类的 jar 位于 Hive 类路径上。
"hbase.struct.autogenerate" = "true" - 指定此属性可让 Hive 使用提供的架构自动推断列和类型。这使您可以避免为 Avro 架构手动创建列和类型,这可能很复杂且嵌套很深。
- 该属性告诉 Hive 给定列族下的给定列是一个 Avro 列,因此 Hive 需要对其进行相应的反序列化。
更多推荐

所有评论(0)