大数据最佳实践 | HBase客户端(上)
Posted 中兴大数据
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据最佳实践 | HBase客户端(上)相关的知识,希望对你有一定的参考价值。
之前两期我们讲了HBase服务端的几项最佳实践,重点在于设计方面。接下来几期我们将讲解HBase客户端的最佳实践,主要通过代码示例的方式为大家说明。
1.1 HBase过滤器
1.1.1问题提出
HBase中两种主要的数据读取函数是get()和scan(),它们都支持直接访问数据以及通过指定起止行键访问数据的功能。也可以在查询中添加更多的限制条件来减少查询得到的数据量,这些限制可以是指定的列族、列、时间戳以及版本号,通过这些方法可以帮助用户控制哪些数据在查询时被包含其中,但是缺少一些细粒度的筛选功能,比如基于正则表达式对行键或值进行筛选。
1.1.2解决思路
HBase Filter(过滤器)为我们提供了非常强大的特性来提高表中数据处理的效率。
常用的主要有以下过滤器:Rowfilter、FamilyDilter、QualifierFilter、ValueFilter、SingleColumnValueFilter、SingleColumnValueExcludeFilter、PrefixFilter、PageFilter、KeyOnlyFilter和FirstKeyOnlyFilter。
1.1.3实践情况
HBase提供以下过滤器的比较操作符:
操作 |
描述 |
LESS |
< |
LESS_OR_EQUAL |
<= |
EQUAL |
= |
NOT_EQUAL |
<> |
GREATER_OR_EQUAL |
>= |
GREATER |
> |
NO_OP |
排除一切值 |
以及比较器:
比较器 |
描述 |
BinaryComparator |
按字节索引顺序比较指定字节数组,采用Bytes.compareTo(byte[]) |
BinaryPrefixComparator |
跟前面相同,只是比较左端的数据是否相同 |
NullComparator |
判断给定的是否为空 |
BitComparator |
按位比较 a BitwiseOp class 做异或,与,并操作 |
RegexStringComparator |
提供一个正则的比较器,仅支持 EQUAL 和NOT_EQUAL |
SubstringComparator |
判断提供的子串是否出现在table的value中 |
接下来我们试用一下几个常用的过滤器。
1)Rowfilter过滤器,通过比较rowkey来确定选择合适的行信息。
构造函数如下:
public RowFilter(org.apache.hadoop.hbase.filter.CompareFilter.CompareOp rowCompareOp, org.apache.hadoop.hbase.filter.WritableByteArrayComparable rowComparator) {} |
示例代码如下:
Scan scan = new Scan(); scan.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-0")); // 精确匹配 Filter filter1 = new RowFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("row-22"))); scan.setFilter(filter1); ResultScanner scanner1 = table.getScanner(scan); System.out.println("Scanning table #1..."); for (Result res : scanner1) { System.out.println(res); } scanner1.close(); // 正则匹配 Filter filter2 = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(".*-.5")); scan.setFilter(filter2); ResultScanner scanner2 = table.getScanner(scan); System.out.println("Scanning table #2..."); for (Result res : scanner2) { System.out.println(res); } scanner2.close(); // 字串匹配 Filter filter3 = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("-5")); scan.setFilter(filter3); ResultScanner scanner3 = table.getScanner(scan); System.out.println("Scanning table #3..."); for (Result res : scanner3) { System.out.println(res); } scanner3.close(); |
2)FamilyFilter过滤器,通过和列族名比较,返回为真的数据。
构造函数如下:
public FamilyFilter(CompareOp familyCompareOp, ByteArrayComparable familyComparator) {} |
示例代码如下:
// 列族名小于指定值 Filter filter1 = new FamilyFilter(CompareFilter.CompareOp.LESS, new BinaryComparator(Bytes.toBytes("colfam3"))); Scan scan = new Scan(); scan.setFilter(filter1); ResultScanner scanner = table.getScanner(scan); System.out.println("Scanning table... "); for (Result result : scanner) { System.out.println(result); } scanner.close(); Get get1 = new Get(Bytes.toBytes("row-5")); get1.setFilter(filter1); Result result1 = table.get(get1); System.out.println("Result of get(): " + result1); // 列族名等于指定值 Filter filter2 = new FamilyFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("colfam3"))); Get get2 = new Get(Bytes.toBytes("row-5")); get2.addFamily(Bytes.toBytes("colfam1")); get2.setFilter(filter2); Result result2 = table.get(get2); System.out.println("Result of get(): " + result2); |
3)QualifierFilter过滤器,通过和列名比较,返回为真的数据。
构造函数如下:
public QualifierFilter(CompareOp qualifierCompareOp, ByteArrayComparable qualifierComparator) {} |
示例代码如下:
//列名小于或者等于指定值 Filter filter = new QualifierFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator( Bytes.toBytes("col-2"))); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); System.out.println("Scanning table... "); for (Result result : scanner) { System.out.println(result); } scanner.close(); Get get = new Get(Bytes.toBytes("row-5")); get.setFilter(filter); Result result = table.get(get); System.out.println("Result of get(): " + result); |
4)ValueFilter过滤器,通过KeyValue比较,返回为真的数据。
构造函数如下:
public ValueFilter(CompareOp valueCompareOp, ByteArrayComparable valueComparator) {} |
示例代码如下:
// 字串匹配 Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(".4")); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); System.out.println("Results of scan:"); for (Result result : scanner) { for (KeyValue kv : result.raw()) { System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue())); } } scanner.close(); Get get = new Get(Bytes.toBytes("row-5")); get.setFilter(filter); Result result = table.get(get); System.out.println("Result of get: "); for (KeyValue kv : result.raw()) { System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue())); } |
5)SingleColumnValueFilter过滤器,选定列簇和某一列,然后与列的value相比,正确的返回全部的row。
构造函数如下:
public SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareOp compareOp, byte[] value) {}; public SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareOp compareOp, ByteArrayComparable comparator) {}; |
示例代码如下:
// 值不匹配 SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5"), CompareFilter.CompareOp.NOT_EQUAL, new SubstringComparator("val-5")); filter.setFilterIfMissing(true); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); System.out.println("Results of scan:"); for (Result result : scanner) { for (KeyValue kv : result.raw()) { System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue())); } } scanner.close(); Get get = new Get(Bytes.toBytes("row-6")); get.setFilter(filter); Result result = table.get(get); System.out.println("Result of get: "); for (KeyValue kv : result.raw()) { System.out.println("KV: " + kv + ", Value: " + Bytes.toString(kv.getValue())); } |
6)SingleColumnValueExcludeFilter过滤器,和SingleColumnValueFilter相反,如果 条件相符,则不返回。
7)PrefixFilter过滤器,所有的row的实例匹配prefix的时候返回结果集合。
构造函数如下:
public PrefixFilter(byte[] prefix) {} |
示例代码如下:
Filter filter = new PrefixFilter(Bytes.toBytes("row1")); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { for (KeyValue kv : result.raw()) { System.out.println("KV:" + kv + ", Value:" + Bytes.toString(kv.getValue())); } } scanner.close(); Get get = new Get(Bytes.toBytes("row-5")); get.setFilter(filter); Result result = table.get(get); for (KeyValue kv : result.raw()) { System.out.println("KV:" + kv + ", Value:" + Bytes.toString(kv.getValue())); } |
8)PageFilter过滤器,页过滤,通过设置pagesize参数可以返回每一页page的数量。
构造函数如下:
public PageFilter(long pageSize) {} |
示例代码如下:
finalbyte[] POSTFIX = newbyte[] { 0x00 }; Filter filter = new PageFilter(15); byte[] lastRow = null; int totalRows = 0; while (true) { Scan scan = new Scan(); scan.setFilter(filter); if (lastRow != null) { byte[] startRow = Bytes.add(lastRow, POSTFIX); scan.setStartRow(startRow); } ResultScanner scanner = table.getScanner(scan); int localRows = 0; Result result; while ((result = scanner.next()) != null) { System.out.println(localRows++ + ":" + result); totalRows++; lastRow = result.getRow(); } scanner.close(); if (localRows == 0) break; } System.out.println("total rows:" + totalRows); |
9)KeyOnlyFilter过滤器,只想获取data数据,而不是真实的val,可以使用这个过滤器。
构造函数如下:
public KeyOnlyFilter(boolean lenAsVal) {} |
lenAsVal默认为假,表示不把val的长度作为val。否则 val的长度将作为val输出。
示例代码如下:
Filter filter = new KeyOnlyFilter(false); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { for (KeyValue kv : result.raw()) { System.out.println(kv + ":" + Bytes.toString(kv.getValue())); } } |
10)FirstKeyOnlyFilter过滤器,在对hbase的表进行扫描的时候,如果指定了FirstKeyOnlyFilter过滤条件则仅仅会返回相同key的第一条kv。当对hbase中的表进行count,sum操作等集合操作的时候,使用FirstKeyOnlyFilter会带来性能上的提升。
构造函数如下:
public FirstKeyOnlyFilter() {} |
示例代码如下:
Filter filter = new FirstKeyOnlyFilter(); Scan scan = new Scan(); scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { for (KeyValue kv : result.raw()) { System.out.println(kv + ":" + Bytes.toString(kv.getValue())); } } |
以上是关于大数据最佳实践 | HBase客户端(上)的主要内容,如果未能解决你的问题,请参考以下文章