HBase建立二级索引的一些解决方式
HBase的一级索引就是rowkey,我们仅仅能通过rowkey进行检索。
假设我们相对hbase里面列族的列列进行一些组合查询。就须要採用HBase的二级索引方案来进行多条件的查询。
常见的二级索引方案有下面几种:
1.MapReduce方案
2.ITHBASE方案
3.IHBASE方案
4.Coprocessor方案
5.Solr+hbase方案
MapReduce方案
IndexBuilder:利用MR的方式构建Index
长处:并发批量构建Index
缺点:不能实时构建Index
举例:
原表:
row 1 f1:name zhangsan
row 2 f1:name lisi
row 3 f1:name wangwu
索引表:
row zhangsan f1:id 1
row lisi f1:id 2
row wangwu f1:id 3
Demo:
package IndexDouble;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.map.HashedMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.HConnection;
import org.apache.hadoop.hbase.client.HConnectionManager;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.MultiTableOutputFormat;
import org.apache.hadoop.hbase.mapreduce.TableInputFormat;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.util.GenericOptionsParser;
public class IndexBuilder {
private String rootDir;
private String zkServer;
private String port;
private Configuration conf;
private HConnection hConn = null;
private IndexBuilder(String rootDir,String zkServer,String port) throws IOException{
this.rootDir = rootDir;
this.zkServer = zkServer;
this.port = port;
conf = HBaseConfiguration.create();
conf.set("hbase.rootdir", rootDir);
conf.set("hbase.zookeeper.quorum", zkServer);
conf.set("hbase.zookeeper.property.clientPort", port);
hConn = HConnectionManager.createConnection(conf);
}
static class MyMapper extends TableMapper<ImmutableBytesWritable, Put>{
//记录了要进行索引的列
private Map<byte[], ImmutableBytesWritable> indexes = new
HashMap<byte[], ImmutableBytesWritable>();
private String familyName;
@Override
protected void map(ImmutableBytesWritable key, Result value,
Context context) throws IOException, InterruptedException {
//原始表列
Set<byte[]> keys = indexes.keySet();
//索引表的rowkey是原始表的列。索引表的列是原始表的rowkey
for (byte[] k : keys){
//获得新建索引表的表名
ImmutableBytesWritable indexTableName = indexes.get(k);
//Result存放的是原始表的数据
//查找到内容 依据列族 和 列 得到原始表的值
byte[] val = value.getValue(Bytes.toBytes(familyName), k);
if (val != null) {
//索引表
Put put = new Put(val);//索引表行键
//列族 列 原始表的行键
put.add(Bytes.toBytes("f1"),Bytes.toBytes("id"),key.get());
context.write(indexTableName, put);
}
}
}
//真正运行Map之前运行一些处理。
@Override
protected void setup(Context context) throws IOException,
InterruptedException {
//通过上下文得到配置
Configuration conf = context.getConfiguration();
//获得表名
String tableName = conf.get("tableName");
//String family = conf.get("familyName");
//获得列族
familyName = conf.get("columnFamily");
//获得列
String[] qualifiers = conf.getStrings("qualifiers");
for (String qualifier : qualifiers) {
//建立一个映射,为每个列创建一个表,表的名字tableName+"-"+qualifier
//原始表的列 索引表新建表名
indexes.put(Bytes.toBytes(qualifier),
new ImmutableBytesWritable(Bytes.toBytes(tableName+"-"+qualifier)));
}
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
String rootDir = "hdfs://hadoop1:8020/hbase";
String zkServer = "hadoop1";
String port = "2181";
IndexBuilder conn = new IndexBuilder(rootDir,zkServer,port);
String[] otherArgs = new GenericOptionsParser(conn.conf, args).getRemainingArgs();
//IndexBuilder: TableName,ColumnFamily,Qualifier
if(otherArgs.length<3){
System.exit(-1);
}
//表名
String tableName = otherArgs[0];
//列族
String columnFamily = otherArgs[1];
conn.conf.set("tableName", tableName);
conn.conf.set("columnFamily", columnFamily);
//列 可能存在多个列
String[] qualifiers = new String[otherArgs.length-2];
for (int i = 0; i < qualifiers.length; i++) {
qualifiers[i] = otherArgs[i+2];
}
//设置列
conn.conf.setStrings("qualifiers", qualifiers);
@SuppressWarnings("deprecation")
Job job = new Job(conn.conf,tableName);
job.setJarByClass(IndexBuilder.class);
job.setMapperClass(MyMapper.class);
job.setNumReduceTasks(0);//因为不须要运行reduce阶段
job.setInputFormatClass(TableInputFormat.class);
job.setOutputFormatClass(MultiTableOutputFormat.class);
Scan scan = new Scan();
TableMapReduceUtil.initTableMapperJob(tableName,scan,
MyMapper.class, ImmutableBytesWritable.class, Put.class, job);
job.waitForCompletion(true);
}
}
创建原始表
hbase(main):002:0> create 'studentinfo','f1'
0 row(s) in 0.6520 seconds
=> Hbase::Table - studentinfo
hbase(main):003:0> put 'studentinfo','1','f1:name','zhangsan'
0 row(s) in 0.1640 seconds
hbase(main):004:0> put 'studentinfo','2','f1:name','lisi'
0 row(s) in 0.0240 seconds
hbase(main):005:0> put 'studentinfo','3','f1:name','wangwu'
0 row(s) in 0.0290 seconds
hbase(main):006:0> scan 'studentinfo'
ROW COLUMN+CELL
1 column=f1:name, timestamp=1436262175823, value=zhangsan
2 column=f1:name, timestamp=1436262183922, value=lisi
3 column=f1:name, timestamp=1436262189250, value=wangwu
3 row(s) in 0.0530 seconds
创建索引表
hbase(main):007:0> create 'studentinfo-name','f1'
0 row(s) in 0.7740 seconds
=> Hbase::Table - studentinfo-name
运行结果
ITHBASE方案
长处:ITHBase(Indexed Transactional HBase)是HBase的一个事物型的带索引的扩展。
缺点:须要重构hbase,几年没有更新。
http://github.com/hbase-trx/hbase-transactional-tableindexed
IHBASE方案
**长处:**IHBase(Indexed HBase)是HBase的一个扩展。用干支持更快的扫描。
缺点:须要重构hbase。
原理:在Memstore满了以后刷磁盘时。IHBase会进行拦截请求,并为这个memstore的数据构建索引。索引还有一个CF的方式存储在表内。scan的时候,IHBase会结合索引列中的标记。来加速scan。
http://github.com/ykulbak/ihbase
Coprocessor方案
HIndex–来自华为的HBase二级索引
http://github.com/Huawei-Hadoop/hindex
The solution is 100% Java, compatible with Apache HBase 0.94.8, and is open sourced under ASL.
Following capabilities are supported currently.
1.multiple indexes on table,
2.multi column index,
3.index based on part of a column value,
4.equals and range condition scans using index, and
5.bulk loading data to indexed table (Indexing done with bulk load).
Solr+hbase方案
Solr是一个独立的企业级搜索应用server,它对并提供相似干Web-service的API接口。用户能够通过http请求,向搜索引擎server提交一定格式的XML文件,生成索引。也能够通过Http Get操作提出查找请求,并得到XML格式的返回结果。
Solr是一个高性能。採用Java5开发。基干Lucene的全文搜索server。同一时候对其进行了扩展。提供了比Lucene更为丰富的查询语言,同一时候实现了可配置、可扩展并对查询性能进行了优化,而且提供了一个完好的功能节理界面。是一款非常优秀的全文搜索引擎。
HBase无可置疑拥有其优势,但其本身仅仅对rowkey支持毫秒级的高速检索,对于多字段的组合查询却无能为力。
基于Solr的HBase多条件查询原理非常easy。将HBase表中涉及条件过滤的字段和rowkey在Solr中建立索引,通过Solr的多条件查询高速获得符合过滤条件的rowkey值,拿到这些rowkey之后在HBASE中通过指定rowkey进行查询。
HBase建立二级索引的一些解决方式的更多相关文章
- 085 HBase的二级索引,以及phoenix的安装(需再做一次)
一:问题由来 1.举例 有A列与B列,分别是年龄与姓名. 如果想通过年龄查询姓名. 正常的检索是通过rowkey进行检索. 根据年龄查询rowkey,然后根据rowkey进行查找姓名. 这样的效率不高 ...
- HBase的二级索引,以及phoenix的安装(需再做一次)
一:HBase的二级索引 1.讲解 uid+ts 11111_20161126111111:查询某一uid的某一个时间段内的数据 查询某一时间段内所有用户的数据:按照时间 索引表 rowkey:ts+ ...
- HBase的二级索引
使用HBase存储中国好声音数据的案例,业务描述如下: 为了能高效的查询到我们需要的数据,我们在RowKey的设计上下了不少功夫,因为过滤RowKey或者根据RowKey查询数据的效率是最高的,我们的 ...
- 基于Solr实现HBase的二级索引
文章来源:http://www.open-open.com/lib/view/open1421501717312.html 实现目的: 由于hbase基于行健有序存储,在查询时使用行健十分高效,然后想 ...
- 利用Phoenix为HBase创建二级索引
为什么需要Secondary Index 对于Hbase而言,如果想精确地定位到某行记录,唯一的办法是通过rowkey来查询.如果不通过rowkey来查找数据,就必须逐行地比较每一列的值,即全表扫瞄. ...
- hbase构建二级索引解决方案
关注公众号:大数据技术派,回复"资料",领取1024G资料. 1 为什么需要二级索引 HBase的一级索引就是rowkey,我们仅仅能通过rowkey进行检索.假设我们相对Hbas ...
- hbase coprocessor 二级索引
Coprocessor方式二级索引 1. Coprocessor提供了一种机制可以让开发者直接在RegionServer上运行自定义代码来管理数据.通常我们使用get或者scan来从Hbase中获取数 ...
- [How to] MapReduce on HBase ----- 简单二级索引的实现
1.简介 MapReduce计算框架是二代hadoop的YARN一部分,能够提供大数据量的平行批处理.MR只提供了基本的计算方法,之所以能够使用在不用的数据格式上包括HBase表上是因为特定格式上的数 ...
- HBase二级索引的设计(案例讲解)
摘要 最近做的一个项目涉及到了多条件的组合查询,数据存储用的是HBase,恰恰HBase对于这种场景的查询特别不给力,一般HBase的查询都是通过RowKey(要把多条件组合查询的字段都拼接在RowK ...
随机推荐
- 【8.20校内测试】【DP】【二分+贪心】
一开始想的贪心,可是发现贪心的问题太多了啊!只能保证当前最优,全局完全无法考虑. 所以正解是dp.预处理出前缀和,枚举每个区间,在每个点记录$now[i]$表示以$i$这个塔结尾的塔组目前的高度.$d ...
- poj 2001 trie
第一道trie 还需要写题来建立自己的代码习惯. #include <cstdio> #include <vector> #include <algorithm> ...
- Javascript中的异步
在C#,Java中,异步方法,通常是伴随多线程,并发等术语一起出现的,比如C#中的async方法,是运行在一个线程池线程上,并且在异步方法运行完成后,有一个回调函数通知主线程. 那么由于Javascr ...
- python开发_IDEL(Python GUI)的使用方法
在这篇blog"Python开发_python的安装"里面你会了解到python的安装. 安装后,我们希望能够运用python GUI来运行一些我们编写的程序,那么Python G ...
- Android Zxing调整扫描区域 优化取图速度
Zxing 是google提供的二维码扫描project Demo本身默认的扫图区域最大仅仅有 360*480 须要拉开非常远的距离才干将整个二维码扫描到 因此须要我们自己调整取图大小 在Cam ...
- LWIP轻量级TCPIP协议栈的移植
http://blog.csdn.net/ygrx/article/details/8020516 好久没有做过技术工作了,前几天因为一些需要,要在ST的OS20平台上进行了LWIP的移植,有一些心得 ...
- The maximum number of processes for the user account running is currently , which can cause performance issues. We recommend increasing this to at least 4096.
[root@localhost ~]# vi /etc/security/limits.conf # /etc/security/limits.conf # #Each line describes ...
- 使用VMware创建Linux虚拟机
准备工作: 下载安装:VMware8.0 (这版本相对稳定,体积小) 下载:rhel-server-5.8-i386-dvd.iso Ready? Go! 1.新建空的虚拟机,相当于多了一台电脑 除了 ...
- Android API 中文(14) —— ViewStub
前言 关键字: android.view.ViewStub,版本为Android 2.2 r1 本章翻译来自唐明 ,这里本博负责整理和发布,欢迎其他译者一起参与Android API 的中文翻译行动, ...
- JS是否存在方法重载
java里面是存在重载的,那么js中呢?这个问题面试的时候会经常遇到.但是可以肯定的说,js中是不存在重载的,但是我们可以通过其他的方式来模拟重载,我们可以通过argument方法来实现. argum ...