• HiveHbase集成实践


    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl/p/6857891.html 转载请注明出处

    简单的说就是可以通过Hive SQL直接对hbase的表进行读写操作,对了,这里可能有人会问,为啥要这么集成呢,有什么场景呢。那我举个场景栗子,比如我们可能会用Hbase做后台历史日志的存储和统计.

    而进行离线日志的存储统计的时候,你当然可以选择用Hadoop MR或者Spark来进行统计和分析并存入相应的Hbase表结构,随后前台可以利用thrift等方式进行实时的查询,ok,这些都能满足需求.

    那么时间长了以后,随着项目需求和数据种类以及临时需求的增多,写MR和Spark会不会很累?所以,当然想到可不可以直接通过Hive SQL来直接读写hbase,这就是一个很普通的需求.

    废话不说,官网有现成的例子可以参考,很详细:https://cwiki.apache.org/confluence/display/Hive/HBaseIntegration

    我整理和总结一下一些细节和遇到的问题

    1.数据准备

    在hive中创建个基础表并插入数据,注意下面红色路径的txt可以在hive的examples目录下找到

    CREATE TABLE pokes (foo INT, bar STRING);
    LOAD DATA LOCAL INPATH '/data/examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;

    2.Hive中创建Hbase表

    这种情况就是在hive和hbase中同时创建新表然后建立hive和hbase的表映射关系,如果删除hive中的表,那么hbase的表也会消失,如下

    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");
    INSERT OVERWRITE TABLE hbase_table_1 SELECT * FROM pokes WHERE foo=98;
    这里解释下,强调一下几点细节

    1>(key int, value string) 和("hbase.columns.mapping" = ":key,cf1:val")以及最后insert后的select的字段,请确定顺序都保持一致

    2>这个hive表和hbase建立的映射就是:hbase的rowkey和hive表的select的第一个字段foo对应,而cf1是列族,val是列名,相当于已经固定好了,select查出的第二个字段就是对应的列值

    3>这里 TBLPROPERTIES 定义了hbase中的表名,如果没有这行,那么hbase默认表名就和hive表名一致

    4>HbaseStorageHandler很重要,hive和hbase的集成需要将hive-hbase-handler-x.y.z.jar(x.y.z是当前环境的jar包版本)配置在Hive client auxpath路径下,也就是说,你必须在

    hive-site.xml里面配置好hive.aux.jars.path,这个属性,而它的值是hive-hbase-handler-x.y.z.jar所在的路径.

    3.Hive映射Hbase多列族多列

    类似于第一种情况,只是映射了多列族多列而已,如下

    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;

    强调的细节和上面那个单列一致,只是多了几个列族和对应的列,这里的列族和列都是提前定义好的.

    scan后结果如下

    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

    4.Hive访问已存在的hbase表

    这种方式其实hive表是个外表,即使清空hive中的表数据,Hbase中的表不会受到影响.

    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");

    5.Hive映射Hbase动态列

    为啥要动态列?因为有的场景下,我需要存入hbase列族下的列名是动态的要存值的是需要查询出来的,不是写死的,如果没有动态映射岂不累死,对应建表和插入如下

    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;

    强调一下几个细节

    1>注意这里表定义mapping的时候,只定义了一个列族名为cf,还有随后的rowkey

    2>注意后面的SELECT的语句,map(bar,foo)中的bar映射的是列名,foo是列值,所以这里是动态的列插入,随后第2个select的列对应的row_key

    3>使用hive map类型时,注意SELECT查出来的字段类型和 “CREATE TABLE hbase_table_1(value map<string,int>, row_key int)”中定义的字段类型需要一致,不然无法插入,详细解释的话,举个栗子

    比如SELECT查出来的map(bar,foo)中列名和列值分别是varchar(50)和bigint类型的话,那么这个时候插入就会报异常然后插入失败

     Cannot insert into target table because column number/types are different

    那么怎么办?我想到二种方式,第一种就是你定义的时候就定义好类型映射保持一致,比如你可以索性将map中的key值在hive中都定义成string类型,另外一种是cast函数,再举个栗子,

    比如SELECT查出来的map(bar,foo)中的bar是varchar(50),foo是bigint,而建立表的时候定义的map<varchar(200),bigint>,这样依然插入不进去,那么可以进行cast,比如cast(bar as varchar(200)),ok,这样可以解决问题.

    参考资料:

    https://cwiki.apache.org/confluence/display/Hive/HBaseIntegration

    http://blog.cloudera.com/blog/2010/06/integrating-hive-and-hbase/

    http://blog.csdn.net/xiaoshunzi111/article/details/51803719

    http://blog.csdn.net/bdchome/article/details/45499641

  • 相关阅读:
    数据结构之c++感悟
    常见linux系统中RPM包的通用命名规则
    scripts
    http
    iscsi
    RHCE认证经典考题
    数据库
    配置空客户端邮件
    配置nfs服务
    Python版本的7大排序
  • 原文地址:https://www.cnblogs.com/cssdongl/p/6857891.html
Copyright © 2020-2023  润新知