关于hbase过滤查询的一些

hbase有两种查询的方式一个get  一个scan

其中get是根据精确的rowkey查出单条的记录    ,那么如果一条记录是有成千上万个字段的话,网络IO大,所以要

get.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("f3"));
get.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("f2"));

来添加和指定要返回的字段

还有一种方式是get.setFilter(filter)   ,这个我没试过


scan 自然也有按照filter来筛选出要返回的字段

filter是这样,客户端可以把filter发送到各个regionserver中,做到在服务端去过滤,从而减少网络IO,而不是说一个简单的scan把所有符合rowkey的都返回给客户端,由客户端来做过滤处理。

如果是get的filter只能做针对列的过滤的话

scan的filter既有针对rowkey的过滤也有针对列的过滤,从而形成一个行列的聚焦。

针对rowkey的filter 用的最多的是前缀过滤

PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes("01_1893300"));  

这里要多说一句,这里前缀实际的所用是包含  也就是说    01_1893300_aa   和  aa_01_1893300 都是符合前缀过滤的

针对列过滤的我这里常用的是列名的filter ,如果要返回多个列的话

QualifierFilter qualifierFilter1 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("f1")));

QualifierFilter qualifierFilter2 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("f2")));

当scan既要对行也要对列进行同时过滤时,要用filterList来整合

但这时要注意,filterLIst只能用来整合列的,不要把列过滤和行过滤都一起整合到filterLIst


例如这里就是


 //先创建一个scan

 Scan scan = new Scan();  

//创建了一个rowkey前缀过滤

PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes("01_1893300"));   

//直接把filter设置到scan中(单独设置)

scan.setFilter(prefixFilter);   

//创建一个fliterList    (Operator.MUST_PASS_ONE,Operator.MUST_PASS_ALL)
 FilterList filterList = new FilterList(Operator.MUST_PASS_ONE);   //要是两个列都含有的话,一定要设置为ONE
//创建两个列过滤  
QualifierFilter qualifierFilter1 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("f1")));
QualifierFilter qualifierFilter2 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("f2")));
//把两个列过滤放到filterLIst中而不要把rowkey行过滤放入  
filterList.addFilter(qualifierFilter1);
filterList.addFilter(qualifierFilter2);

//把这个filterList设置到scan中
scan.setFilter(filterList);   

这样才会过滤下来你指定的行 和 指定的列的值,其他的都不会通过网络传到客户端了


另外hbase是设计成按照rowkey来查询才能最大化查询效率的,我没有用过二级索引,所以就不说这个了

那么如果单通过列值来过滤话就会效果很差

还有如果通过filter查到了也就罢了,如果filter后查不到,响应速度就会很慢,会有十几秒

所以当用filter时要加个判断

if (result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("f2")) != null) {
System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("cf"),Bytes.toBytes("f2"))));
}


那么分别给个get  和  scan  的带过滤的查询的列子



// Table table = HbaseUtils.getHTable();
// Get get = new Get(Bytes.toBytes("01_1893300_aa"));
get.setFilter(filter)
//
// get.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("f3"));
// get.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("f2"));
//
// Result result = table.get(get);
//
// System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("f1"))));  // result.getRow()  是获得rowkey




//-------------------------


Table table = HbaseUtils.getHTable();
Scan scan = new Scan();  
FilterList filterList = new FilterList(Operator.MUST_PASS_ONE);
PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes("01_1893300"));    //前缀的话  ,其实不在前缀也是可以的
QualifierFilter qualifierFilter1 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("f1")));
QualifierFilter qualifierFilter2 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("f2")));
 
filterList.addFilter(qualifierFilter1);
filterList.addFilter(qualifierFilter2);


scan.setFilter(prefixFilter);   
 
scan.setFilter(filterList);   

      ResultScanner scanner = table.getScanner(scan);  

      for (Result result : scanner) {
      
      
    // 判断取出来的值是否为空
if (result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("f2")) != null) {
System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("cf"),Bytes.toBytes("f2"))));
}
      
// 判断取出来的值是否为空
if (result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("f3")) != null) {
System.out.println(Bytes.toString(result.getValue(Bytes.toBytes("cf"),Bytes.toBytes("f3"))));
}

      }

最后多说一句 以手机号为例  183**********

如果hbase的业务偏向查询的话,那手机号最好正写,当批量查询是会从同一个region出,效率高

如果hbase的业务偏向插入的话,那手机号最好反写,当批量插入的时候,写时分布平衡




参考

http://www.cnblogs.com/kxdblog/p/4328699.html

http://www.cnblogs.com/skyl/p/4807793.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值