HBase Bulk Loading
将数据导入到HBase有三种方式:(1) Mapreduce,输出为TableOutputFormat
.(2) 用HBase API .(3)Bulk Loading。对于大量的数据入库,第三种数据是最为有效的。
下图描述了Bulk Loading的过程:先将数据(MySQL ,Oracle ,文本文件等)加载到HDFS,通过MapReduce 将数据做成HFile (HFileOutPutForm)。然后使用HBase提供的CompleteBulkLoad(LoadIncrementalHFiles)工具加载到HBase中,这个过程很快,而且不很耗内存,不影响在线的Hbase
集群的正常操作。因为这个过程不需要结果WAL 和Memstore.
注意事项:
(1)配置一个total order partitioner。
(2)reduce 个数要和表的region 数目匹配。
(3)MR 输出的Key/Value 类型要和HFileOutPutFormat的匹配。
(4)reduce 采用KeyValueSortReducer 或者PutSortReducer。
应用场景:
(1)集群上线,原始数据集加载。
(2)数据增量。需要定期将MySql(Oracle) 的数据导入HBase。
(3)经常性的大批量入库。
对于CSV文件的加载:
hadoop jar /usr/lib/hbase/hbase-0.94.6-cdh4.3.0-
security.jar importtsv
-Dimporttsv.separator=,
-Dimporttsv.bulk.output=output
-Dimporttsv.columns=HBASE_ROW_KEY,f:count wordcount word_count.csv
该文件的数据格式为---> rowkey,列:值 。
导入到的表名为wordcount ,数据文件为word_count.csv
这样做,不会生成wordcount表。
执行
hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles output wordcount
入库完成。
hadoop jar /usr/lib/hbase/hbase-0.94.6-cdh4.3.0-
security.jar importtsv
-Dimporttsv.separator=,
-Dimporttsv.columns=HBASE_ROW_KEY,f:count wordcount word_count.csv
这样做一步到位,直接入库。
或者用
HADOOP_CLASSPATH=`${HBASE_HOME}/bin/hbase classpath` ${HADOOP_HOME}/bin/hadoop jar ${HBASE_HOME}/hbase-VERSION.jar completebulkload <hdfs://storefileoutput> <tablename>
同样 一步到位,直接入库。
下面是一个MR生成HFile的例子:
import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.Path;import org.apache.hadoop.hbase.HBaseConfiguration;import org.apache.hadoop.hbase.KeyValue;import org.apache.hadoop.hbase.client.HTable;import org.apache.hadoop.hbase.io.ImmutableBytesWritable;import org.apache.hadoop.hbase.mapreduce.HFileOutputFormat;import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;import org.apache.hadoop.mapreduce.Job;import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import org.apache.hadoop.util.GenericOptionsParser;/*** HBase bulk import example<br>* Data preparation MapReduce job driver* <ol>* <li>args[0]: HDFS input path* <li>args[1]: HDFS output path* <li>args[2]: HBase table name* </ol>*/public class Driver {public static void main(String[] args) throws Exception {Configuration conf = new Configuration();args = new GenericOptionsParser(conf, args).getRemainingArgs();/** NBA Final 2010 game 1 tip-off time (seconds from epoch)* Thu, 03 Jun 2010 18:00:00 PDT*/conf.setInt("epoch.seconds.tipoff", 1275613200);conf.set("hbase.table.name", args[2]);// Load hbase-site.xmlHBaseConfiguration.addHbaseResources(conf);Job job = new Job(conf, "HBase Bulk Import Example");job.setJarByClass(HBaseKVMapper.class);job.setMapperClass(HBaseKVMapper.class);job.setMapOutputKeyClass(ImmutableBytesWritable.class);job.setMapOutputValueClass(KeyValue.class);job.setInputFormatClass(TextInputFormat.class);HTable hTable = new HTable(args[2]);// Auto configure partitioner and reducerHFileOutputFormat.configureIncrementalLoad(job, hTable);FileInputFormat.addInputPath(job, new Path(args[0]));FileOutputFormat.setOutputPath(job, new Path(args[1]));job.waitForCompletion(true);}}import java.io.IOException;import java.util.Locale;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.hbase.KeyValue;import org.apache.hadoop.hbase.io.ImmutableBytesWritable;import org.apache.hadoop.io.LongWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.Mapper;import org.joda.time.DateTime;import org.joda.time.DateTimeZone;import org.joda.time.format.DateTimeFormat;import org.joda.time.format.DateTimeFormatter;import au.com.bytecode.opencsv.CSVParser;/*** HBase bulk import example* <p>* Parses Facebook and Twitter messages from CSV files and outputs* <ImmutableBytesWritable, KeyValue>.* <p>* The ImmutableBytesWritable key is used by the TotalOrderPartitioner to map it* into the correct HBase table region.* <p>* The KeyValue value holds the HBase mutation information (column family,* column, and value)*/public class HBaseKVMapper extendsMapper<LongWritable, Text, ImmutableBytesWritable, KeyValue> {final static byte[] SRV_COL_FAM = "srv".getBytes();final static int NUM_FIELDS = 16;CSVParser csvParser = new CSVParser();int tipOffSeconds = 0;String tableName = "";DateTimeFormatter p = DateTimeFormat.forPattern("MMM dd, yyyy HH:mm:ss").withLocale(Locale.US).withZone(DateTimeZone.forID("PST8PDT"));ImmutableBytesWritable hKey = new ImmutableBytesWritable();KeyValue kv;/** {@inheritDoc} */@Overrideprotected void setup(Context context) throws IOException,InterruptedException {Configuration c = context.getConfiguration();tipOffSeconds = c.getInt("epoch.seconds.tipoff", 0);tableName = c.get("hbase.table.name");}/** {@inheritDoc} */@Overrideprotected void map(LongWritable key, Text value, Context context)throws IOException, InterruptedException {if (value.find("Service,Term,") > -1) {// Skip headerreturn;}String[] fields = null;try {fields = csvParser.parseLine(value.toString());} catch (Exception ex) {context.getCounter("HBaseKVMapper", "PARSE_ERRORS").increment(1);return;}if (fields.length != NUM_FIELDS) {context.getCounter("HBaseKVMapper", "INVALID_FIELD_LEN").increment(1);return;}// Get game offset in seconds from tip-offDateTime dt = null;try {dt = p.parseDateTime(fields[9]);} catch (Exception ex) {context.getCounter("HBaseKVMapper", "INVALID_DATE").increment(1);return;}int gameOffset = (int) ((dt.getMillis() / 1000) - tipOffSeconds);String offsetForKey = String.format("%04d", gameOffset);String username = fields[2];if (username.equals("")) {username = fields[3];}// Key: e.g. "1200:twitter:jrkinley"hKey.set(String.format("%s:%s:%s", offsetForKey, fields[0], username).getBytes());// Service columnsif (!fields[0].equals("")) {kv = new KeyValue(hKey.get(), SRV_COL_FAM,HColumnEnum.SRV_COL_SERVICE.getColumnName(), fields[0].getBytes());context.write(hKey, kv);}if (!fields[1].equals("")) {kv = new KeyValue(hKey.get(), SRV_COL_FAM,HColumnEnum.SRV_COL_TERM.getColumnName(), fields[1].getBytes());context.write(hKey, kv);}if (!fields[2].equals("")) {kv = new KeyValue(hKey.get(), SRV_COL_FAM,HColumnEnum.SRV_COL_USERNAME.getColumnName(), fields[2].getBytes());context.write(hKey, kv);}if (!fields[3].equals("")) {kv = new KeyValue(hKey.get(), SRV_COL_FAM,HColumnEnum.SRV_COL_NAME.getColumnName(), fields[3].getBytes());context.write(hKey, kv);}if (!fields[4].equals("")) {kv = new KeyValue(hKey.get(), SRV_COL_FAM,HColumnEnum.SRV_COL_UPDATE.getColumnName(), fields[4].getBytes());context.write(hKey, kv);}if (!fields[9].equals("")) {kv = new KeyValue(hKey.get(), SRV_COL_FAM,HColumnEnum.SRV_COL_TIME.getColumnName(), fields[9].getBytes());context.write(hKey, kv);}context.getCounter("HBaseKVMapper", "NUM_MSGS").increment(1);/** Output number of messages per quarter and before/after game. This should* correspond to the number of messages per region in HBase*/if (gameOffset < 0) {context.getCounter("QStats", "BEFORE_GAME").increment(1);} else if (gameOffset < 900) {context.getCounter("QStats", "Q1").increment(1);} else if (gameOffset < 1800) {context.getCounter("QStats", "Q2").increment(1);} else if (gameOffset < 2700) {context.getCounter("QStats", "Q3").increment(1);} else if (gameOffset < 3600) {context.getCounter("QStats", "Q4").increment(1);} else {context.getCounter("QStats", "AFTER_GAME").increment(1);}}}
/*** HBase table columns for the 'srv' column family*/public enum HColumnEnum {SRV_COL_SERVICE ("service".getBytes()),SRV_COL_TERM ("term".getBytes()),SRV_COL_USERNAME ("username".getBytes()),SRV_COL_NAME ("name".getBytes()),SRV_COL_UPDATE ("update".getBytes()),SRV_COL_TIME ("pdt".getBytes());private final byte[] columnName;HColumnEnum (byte[] column) {this.columnName = column;}public byte[] getColumnName() {return this.columnName;}}
HBase Bulk Loading的更多相关文章
- How-to: Use HBase Bulk Loading, and Why
How-to: Use HBase Bulk Loading, and Why http://blog.cloudera.com/blog/2013/09/how-to-use-hbase-bulk- ...
- How To Use Hbase Bulk Loading
最近在学习hbase,学到利用如何将数据导入到hbase中,采用的方式是批量导入:bulk load的方法,中间出现了一些问题,下面将执行的步骤记录一下,以供日后查阅: 说明:导入的方式是将csv文件 ...
- HBase高速导入数据--BulkLoad
Apache HBase是一个分布式的.面向列的开源数据库.它能够让我们随机的.实时的訪问大数据.可是如何有效的将数据导入到HBase呢?HBase有多种导入数据的方法.最直接的方法就是在MapRed ...
- 通过BulkLoad的方式快速导入海量数据
摘要 加载数据到HBase的方式有多种,通过HBase API导入或命令行导入或使用第三方(如sqoop)来导入或使用MR来批量导入(耗费磁盘I/O,容易在导入的过程使节点宕机),但是这些方式不是慢就 ...
- Sqoop学习之路 (一)
一.概述 sqoop 是 apache 旗下一款“Hadoop 和关系数据库服务器之间传送数据”的工具. 核心的功能有两个: 导入.迁入 导出.迁出 导入数据:MySQL,Oracle 导入数据到 H ...
- Hadoop生态圈-Sqoop部署以及基本使用方法
Hadoop生态圈-Sqoop部署以及基本使用方法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Sqoop(发音:skup)是一款开源的工具,主要用于在Hadoop(Hive)与 ...
- sqoop导入数据
来源https://www.cnblogs.com/qingyunzong/p/8807252.html 一.概述 sqoop 是 apache 旗下一款“Hadoop 和关系数据库服务器之间传送数据 ...
- 【Sqoop学习之二】Sqoop使用
环境 sqoop-1.4.6 一.基本命令1.帮助命令 [root@node101 ~]# sqoop help Warning: /usr/local/sqoop-/../hbase does no ...
- Bulk Load-HBase数据导入最佳实践
一.概述 HBase本身提供了非常多种数据导入的方式,通常有两种经常使用方式: 1.使用HBase提供的TableOutputFormat,原理是通过一个Mapreduce作业将数据导入HBase 2 ...
随机推荐
- Java安全管理器——SecurityManager
总的来说,Java安全应该包括两方面的内容,一是Java平台(即是Java运行环境)的安全性:二是Java语言开发的应用程序的安全性.由于我们不是Java本身语言的制定开发者,所以第一个安全性不需要我 ...
- windows下安装nginx (转载自:http://blog.163.com/njut_wangjian/blog/static/1657964252013327103716818/)
1. 到nginx官网上下载相应的安装包,http://nginx.org/en/download.html:下载进行解压,将解压后的文件放到自己心仪的目录下,我的解压文件放在了d盘根目录下,如下图 ...
- ExtJS学习(三)Grid表格
表格说明 Ext中的表格功能非常强大,包括排序.缓存.拖动.隐藏某一列.自动显示行号.列汇总.单元格编辑等实用功能.表格由类Ext.grid.GridPanel定义,继承自Ext.Panel,其xty ...
- Objc中为何某些类的属性要设置为copy而不是strong?
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 不知道大家是否注意,我们再使用一些第三方类的时候大多数情况下对 ...
- android程序崩溃后重启
有时候由于测试不充分或者程序潜在的问题而导致程序异常崩溃,这个是令人无法接受的,在android中怎样捕获程序的异常崩溃,然后进行一些必要的处理或重新启动 应用这个问题困恼了我很久,今天终于解决了该问 ...
- 没想到你是这样的UDP
UDP是国际标准化组织为互联网设定的标准中的传输层中的一个协议.TCP/IP协议簇是一个很庞大的家族,但是今天我们就来看一看这个面向无连接的传输层在Java中是怎样通过编程实现的. 原理性知识 在Ja ...
- SDL2源代码分析5:更新纹理(SDL_UpdateTexture())
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- 【一天一道LeetCode】#104. Maximum Depth of Binary Tree
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 来源:http ...
- 多态原理探究-从C++编译器角度理解多态的实现原理
理论知识: 当类中声明虚函数时,编译器会在类中生成一个虚函数表. 虚函数表是一个存储类成员函数指针的数据结构. 虚函数表是由编译器自动生成与维护的. virtual成员函数会被编译器放入虚函数表中. ...
- Leetcode_38_count-and-say
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41257397 The count-and-say sequ ...