Hive 数据导入HBase的2种方法详解

Stella981
• 阅读 1245

最近经常被问到这个问题,所以简单写一下总结。

Hive数据导入到HBase基本有2个方案:

    1、HBase中建表,然后Hive中建一个外部表,这样当Hive中写入数据后,HBase中也会同时更新

    2、MapReduce读取Hive数据,然后写入(API或者Bulkload)到HBase

1、Hive 外部表

创建hbase表

(1) 建立一个表格classes具有1个列族user

create 'classes','user'

(2) 查看表的构造

hbase(main):005:0> describe 'classes'
DESCRIPTION ENABLED
 'classes', {NAME => 'user', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'ROW', REPLICATION_SCOPE => '0', true
  VERSIONS => '1', COMPRESSION => 'NONE', MIN_VERSIONS => '0', TTL => '2147483647', KEEP_DELETED_CELLS => '
 false', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'}

(3) 加入2行数据

put 'classes','001','user:name','jack'
put 'classes','001','user:age','20'
put 'classes','002','user:name','liza'
put 'classes','002','user:age','18'

(4) 查看classes中的数据

hbase(main):016:0> scan 'classes'
ROW COLUMN+CELL
 001 column=user:age, timestamp=1404980824151, value=20
 001 column=user:name, timestamp=1404980772073, value=jack
 002 column=user:age, timestamp=1404980963764, value=18
 002 column=user:name, timestamp=1404980953897, value=liza

(5) 创建外部hive表,查询验证

create external table classes(id int, name string, age int) 
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' 
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,user:name,user:age") 
TBLPROPERTIES("hbase.table.name" = "classes");

select * from classes;
OK
1 jack 20
2 liza 18

(6)再添加数据到HBase

put 'classes','003','user:age','1820183291839132'
hbase(main):025:0> scan 'classes'
ROW COLUMN+CELL
 001 column=user:age, timestamp=1404980824151, value=20
 001 column=user:name, timestamp=1404980772073, value=jack
 002 column=user:age, timestamp=1404980963764, value=18
 002 column=user:name, timestamp=1404980953897, value=liza
 003 column=user:age, timestamp=1404981476497, value=1820183291839132

(7)Hive查询,看看新数据

select * from classes;
OK
1 jack 20
2 liza 18
3 NULL NULL    --这里是null了,因为003没有name,所以补位Null,而age为Null是因为超过最大值

(8)如下作为验证

put 'classes','004','user:name','test'
put 'classes','004','user:age','1820183291839112312'  -- 已经超int了
hbase(main):030:0> scan 'classes'
ROW COLUMN+CELL
 001 column=user:age, timestamp=1404980824151, value=20
 001 column=user:name, timestamp=1404980772073, value=jack
 002 column=user:age, timestamp=1404980963764, value=18
 002 column=user:name, timestamp=1404980953897, value=liza
 003 column=user:age, timestamp=1404981476497, value=1820183291839132
 004 column=user:age, timestamp=1404981558125, value=1820183291839112312
 004 column=user:name, timestamp=1404981551508, value=test                   
select * from classes;
1 jack 20
2 liza 18
3 NULL NULL
4 test NULL    -- 超int后也认为是null
put 'classes','005','user:age','1231342'
hbase(main):034:0* scan 'classes'
ROW COLUMN+CELL
 001 column=user:age, timestamp=1404980824151, value=20
 001 column=user:name, timestamp=1404980772073, value=jack
 002 column=user:age, timestamp=1404980963764, value=18
 002 column=user:name, timestamp=1404980953897, value=liza
 003 column=user:age, timestamp=1404981476497, value=1820183291839132
 004 column=user:age, timestamp=1404981558125, value=1820183291839112312
 004 column=user:name, timestamp=1404981551508, value=test
 005 column=user:age, timestamp=1404981720600, value=1231342   
select * from classes;
1 jack 20
2 liza 18
3 NULL NULL
4 test NULL
5 NULL 1231342

注意点:

    1、hbase中的空cell在hive中会补null

    2、hive和hbase中不匹配的字段会补null

    3、Bytes类型的数据,建hive表示加#b

http://stackoverflow.com/questions/12909118/number-type-value-in-hbase-not-recognized-by-hive

    http://www.aboutyun.com/thread-8023-1-1.html

4、HBase CF to hive Map

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

2、MapReduce 写入 HBase

    MR写入到HBase有2个常用方法,1是直接调用HBase Api,使用Table 、Put写入;2是通过MR生成HFile,然后Bulkload到HBase,数据量很大的时候推荐使用

注意点:

1、如果需要从hive的路径中读取一些值怎么办

private String reg = "stat_date=(.*?)\\/softid=([\\d]+)/";
private String stat_date;
private String softid;
 ------------厦门map函数中写入-------------
String filePathString = ((FileSplit) context.getInputSplit()).getPath().toString();
///user/hive/warehouse/snapshot.db/stat_all_info/stat_date=20150820/softid=201/000000_0
// 解析stat_date 和softid
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(filePathString);
while(matcher.find()){
    stat_date = matcher.group(1);
    softid = matcher.group(2);
}

2、hive中的map和list怎么处理

hive中的分隔符主要有8种,分别是\001-----> \008

默认    ^A    \001
,       ^B    \002
:       ^C    \003

 Hive中保存的Lis,最底层的数据格式为 jerrick,  liza, tom, jerry , Map的数据格式为  jerrick:23, liza:18, tom:0

所以在MR读入时需要简单处理下,例如map需要:   "{"+ mapkey.replace("\002", ",").replace("\003", ":")+"}", 由此再转为JSON, toString后再保存到HBase。

    3、简单实例,代码删减很多,仅可参考!

public void map(
                LongWritable key,
                Text value,
                Mapper<LongWritable, Text, ImmutableBytesWritable, KeyValue>.Context context) {
                String filePathString = ((FileSplit) context.getInputSplit()).getPath().toString();
                ///user/hive/warehouse/snapshot.db/stat_all_info/stat_date=20150820/softid=201/000000_0
                // 解析stat_date 和softid
                Pattern pattern = Pattern.compile(reg);
                Matcher matcher = pattern.matcher(filePathString);
                while(matcher.find()){
                    stat_date = matcher.group(1);
                    softid = matcher.group(2);
                }
                
                rowMap.put("stat_date", stat_date);
                rowMap.put("softid", softid);
                
                String[] vals = value.toString().split("\001");
                
                try {
                    Configuration conf = context.getConfiguration();
                    String cf = conf.get("hbase.table.cf", HBASE_TABLE_COLUME_FAMILY);
                    
                    String arow = rowkey; 
                    for(int index=10; index < vals.length; index++){
                        byte[] row = Bytes.toBytes(arow);
                        ImmutableBytesWritable k = new ImmutableBytesWritable(row);
                        KeyValue kv = new KeyValue();
                        if(index == vals.length-1){
                            //dict need 
                            logger.info("d is :" + vals[index]);
                            logger.info("d is :" + "{"+vals[index].replace("\002", ",").replace("\003", ":")+"}");
                            
                            
                            JSONObject json = new JSONObject("{"+vals[index].replace("\002", ",").replace("\003", ":")+"}");
                            kv = new KeyValue(row, cf.getBytes(),Bytes.toBytes(valueKeys[index]), Bytes.toBytes(json.toString()));
                        }else{
                            kv = new KeyValue(row, cf.getBytes(),Bytes.toBytes(valueKeys[index]), Bytes.toBytes(vals[index]));
                        }
                        context.write(k, kv);
                    }
                    
                } catch (Exception e1) {
                    context.getCounter("offile2HBase", "Map ERROR").increment(1);
                    logger.info("map error:" + e1.toString());
                }
                
            context.getCounter("offile2HBase", "Map TOTAL").increment(1);

        }
    }

   4、bulkload

int jobResult = (job.waitForCompletion(true)) ? 0 : 1;
logger.info("jobResult=" + jobResult);
Boolean bulkloadHfileToHbase = Boolean.valueOf(conf.getBoolean("hbase.table.hfile.bulkload", false));
if ((jobResult == 0) && (bulkloadHfileToHbase.booleanValue())) {
    LoadIncrementalHFiles loader = new LoadIncrementalHFiles(conf);
    loader.doBulkLoad(outputDir, hTable);
}
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Hive重写表数据丢失风险记录
若在Hive中执行INSERTOVERWRITE重写同一个表的数据时,有可能会造成数据丢失。如INSERTOVERWRITETABLEtable\_nameSELECT\FROMtable\_name一、新建一张分区表createtabletest_chj_cols(idstr
Stella981 Stella981
2年前
Hive内部表和外部表的区别详解
内部表&外部表未被external修饰的是内部表(managedtable),被external修饰的为外部表(externaltable);区别:内部表数据由Hive自身管理,外部表数据由HDFS管理;内部表数据存储的位置是hive.metastore.warehouse.dir(默认:/user/hive/warehouse)
Stella981 Stella981
2年前
Hive建表的Location问题
最近公司在使用Hive做项目测试,所以就在Hive上面建了一些表,做测试。使用建表语句后发现数据被自动覆盖了,现在了解到的情况是这样的。Hive中,表的Metadata信息全部存储在MySQL中。而存储在MySQL中的数据是没有校验过程的。也就是说,你可以创建一个逻辑错误的表,两个表指向同一个HDFS文件也是有可能的。所以,在使用CREA
Stella981 Stella981
2年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Stella981 Stella981
2年前
Hive使用必知必会系列
一、Hive的几种数据模型内部表(Table将数据保存到Hive自己的数据仓库目录中:/usr/hive/warehouse)外部表(ExternalTable相对于内部表,数据不在自己的数据仓库中,只保存数据的元信息)分区表
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这