该系列博文为笔者学习使用hbase时笔记,能使快速入门hbase的一些使用。如发现问题,欢迎批评指正。
【Hbase学习系列】Hbase常用过滤器使用详解
- 1. hbase全表查询的一个例子
- 2. 比较过滤器(CompareFiter)
- 2.1 行键过滤器(RowFilter)
- 2.1.1 CompareOperator
- 2.1.2 ByteArrayComparable
- 2.2 列簇过滤器(FamilyFilter)
- 2.3 列过滤器(QualifierFilter)
- 2.4 值过滤器(ValueFilter)
- 2.5 参考列过滤器(DependentColumnFilter)
- 3. 多过滤器(FilterList)
1. hbase全表查询的一个例子
在介绍hbase过滤器之前,先给出hbase全表查询的一个例子。在查询数据时,使用添加了过滤器的scan对象,过滤器即可生效,具体实现如下:
① 需要引入的依赖
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-mapreduce</artifactId>
<version>2.0.4</version>
</dependency>
② 具体java代码实现
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.CompareOperator;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import java.io.IOException;
/**
* Created by search-lemon on 2020/9/29.
*/
public class HbaseTest {
private static Connection conn;
public static void main(String[] args) {
try {
initHbaseConn();
Scan scan = new Scan();
query(scan);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 初始化Hbase连接.
*/
public static void initHbaseConn() throws IOException {
Configuration conf = HBaseConfiguration.create();
conf.set(HConstants.ZOOKEEPER_QUORUM, "**********"); // 这里写入hbase client的zk
conf.set(HConstants.ZOOKEEPER_CLIENT_PORT, "****"); // 这里写入zk的port
conf.set(HConstants.HBASE_CLIENT_PAUSE, "50"); // 失败重试等待时间
conf.set(HConstants.HBASE_CLIENT_RETRIES_NUMBER, "3"); // 失败重试次数.
conn = ConnectionFactory.createConnection(conf);
}
/**
* 根据不同scan查询hbase数据.
*/
public static void query(Scan scan) throws IOException {
Table table = conn.getTable(TableName.valueOf("test1")); // 表名为test1
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
byte[] rowKey = result.getRow();
System.out.print(new String(rowKey) + "\t");
for (Cell cell : result.listCells()) {
String family = new String(CellUtil.cloneFamily(cell));
String qualifier = new String(CellUtil.cloneQualifier(cell));
String value = new String(CellUtil.cloneValue(cell));
System.out.print(family + ":" + qualifier + " " + value + "\t");
}
System.out.println();
}
}
}
③ 运行结果:(笔者在hbase的test1表中预先写入了两条数据,用来演示下面不同过滤器的效果)
http://www.test7 f1:host 894spark f1:ip 1239843
http://www.test8 f1:host 8932spark f1:ip 4568390
2. 比较过滤器(CompareFiter)
比较过滤器可实例化的类有5个,其父类为抽象类CompareFilter。类图如下:
下面介绍几个常用的比较过滤器的使用方法:
2.1 行键过滤器(RowFilter)
Hbase行键过滤使用RowFilter类实现,使用方式如下:
Filter rowFilter = new RowFilter(CompareOperator.EQUAL, new RegexStringComparator(".*test7"));
scan.setFilter(rowFilter);
运行结果:
http://www.test7 f1:host 894spark f1:ip 1239843
2.1.1 CompareOperator
RowFilter初始化时,参数1:CompareOperator为比较操作的枚举类,包含如下枚举常量:
CompareOperator中枚举常量 | 含义 |
LESS | 小于 < |
LESS_OR_EQUAL | 小于等于 <= |
EQUAL | 等于 = |
NOT_EQUAL | 不等于 != |
GREATER_OR_EQUAL | 大于等于 >= |
GREATER | 大于 > |
NO_OP | 排除一切(Exclude everything) |
注:比较运算符枚举类CompareOp(使用方式:CompareFilter.
CompareOp.EQUAL)作用等价于CompareOperator。在2.0.0版本该类被弃用,在3.0.0版本会被移除,因此建议使用CompareOperator。
2.1.2 ByteArrayComparable
参数2:ByteArrayComparable为实现了Comparable<byte[]>接口的比较器,源码中其实例化可用子类有:RegexStringComparator
,BinaryPrefixComparator
,SubstringComparator
,BinaryComparator
,BigDecimalComparator
,BitComparator
,LongComparator
,NullComparator
。
各比较器使用方式如下:
- RegexStringComparator
// 匹配行键以"http"开头的行
new RowFilter(CompareOperator.EQUAL, new RegexStringComparator("^http.*");
// 运行结果:
http://www.test7 f1:host 894spark f1:ip 1239843
http://www.test8 f1:host 8932spark f1:ip 4568390
注:使用RegexStringComparator时,其它文章中都写的”仅支持 EQUAL 和 NOT_EQUAL 操作“,但笔者经测试其它运算符也是生效的,如上例中,使用NO_OP即过滤掉所有数据,使用LESS_OR_EQUAL两条数据都输出,LESS将两条都过滤掉了。但从运算逻辑角度出发,建议还是尽量只使用EQUAL 和 NOT_EQUAL,避免出现其它意想不到的结果。
- BinaryPrefixComparator
// 匹配行键以"http"开头的行
new RowFilter(CompareOperator.EQUAL, new BinaryPrefixComparator("http".getBytes()));
// 运行结果:
http://www.test7 f1:host 894spark f1:ip 1239843
http://www.test8 f1:host 8932spark f1:ip 4568390
- SubstringComparator
// 匹配行键包含“test7”的行
new RowFilter(CompareOperator.EQUAL, new SubstringComparator("test7"));
// 运行结果
http://www.test7 f1:host 894spark f1:ip 1239843
- BinaryComparator
// 匹配行键为“http://www.test7”的行
new RowFilter(CompareOperator.EQUAL, new BinaryComparator("http://www.test7".getBytes()));
// 运行结果
http://www.test7 f1:host 894spark f1:ip 1239843
- BigDecimalComparator
// 匹配行键不为BigDecimal类型123的行
new RowFilter(CompareOperator.NOT_EQUAL, new BigDecimalComparator(new BigDecimal(123)));
// 运行结果
http://www.test7 f1:host 894spark f1:ip 1239843
http://www.test8 f1:host 8932spark f1:ip 4568390
- BitComparator
// 匹配行键与Byte[]类型"123"按位与结果为false的行(建议应当使用数值类型比较,这里只是为了简单说明比较器的作用)
new RowFilter(CompareOperator.NOT_EQUAL, new BitComparator("123".getBytes(), BitComparator.BitwiseOp.AND));
// 运行结果
http://www.test7 f1:host 894spark f1:ip 1239843
http://www.test8 f1:host 8932spark f1:ip 4568390
- LongComparator
// 匹配行键为Long类型123的行
new RowFilter(CompareOperator.EQUAL, new LongComparator(123L));
// 运行结果
Caused by: org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=4, exceptions:
Wed Sep 30 15:24:57 GMT+08:00 2020, RpcRetryingCaller{globalStartTime=1601450696785, pause=50, maxAttempts=4}, java.io.IOException: java.io.IOException: Wrong length: 16, expected 8
注:由于本文例中两条数据的行键为String类型,长度为16。而LongComparator只能比较两个Long类型的数值,因此报错Byte[]数组长度有误。
- NullComparator
// 匹配行键不为空的行
new RowFilter(CompareOperator.NOT_EQUAL, new NullComparator());
// 运行结果
http://www.test7 f1:host 894spark f1:ip 1239843
http://www.test8 f1:host 8932spark f1:ip 4568390
2.2 列簇过滤器(FamilyFilter)
Filter filter = new FamilyFilter(CompareOperator.EQUAL, new BinaryComparator("f1".getBytes()));
scan.setFilter(filter);
运行结果:
http://www.test7 f1:host 894spark f1:ip 1239843
http://www.test8 f1:host 8932spark f1:ip 4568390
2.3 列过滤器(QualifierFilter)
Filter filter = new QualifierFilter(CompareOperator.EQUAL, new BinaryComparator("host".getBytes()));
scan.setFilter(filter);
运行结果:
http://www.test7 f1:host 894spark
http://www.test8 f1:host 8932spark
2.4 值过滤器(ValueFilter)
Filter filter = new ValueFilter(CompareOperator.EQUAL, new RegexStringComparator(".*spark"));
scan.setFilter(filter);
运行结果:
http://www.test7 f1:host 894spark
http://www.test8 f1:host 8932spark
2.5 参考列过滤器(DependentColumnFilter)
DependentColumnFilter是基于指定目标参考列的时间戳,用来过滤其它列的值,举例如下:
Filter filter = new DependentColumnFilter("f1".getBytes(), "host".getBytes());
scan.setFilter(filter);
运行结果:
http://www.test7 f1:host 894spark f1:ip 1239843
http://www.test8 f1:host 8932spark f1:ip 4568390
上例中,由于f1:host 和 f1:ip是同时写入hbase表中的,所以过滤后,两条数据都留下来了。但当重新再向表中单独写入相同的f1:host列的值时(表中数据不表,只是f1:host 和 f1:ip这两列写入时间不同),运行相同的代码,结果如下:
http://www.test7 f1:host 894spark
http://www.test8 f1:host 8932spark
3. 多过滤器(FilterList)
Hbase中多个过滤器可组合使用,用FilterList来实现,使用方式如下:
Filter filter1 = new RowFilter(CompareOperator.EQUAL, new RegexStringComparator(".*test7"));
Filter filter2 = new ValueFilter(CompareOperator.EQUAL, new RegexStringComparator(".*spark"));
FilterList filters = new FilterList(filter1, filter2);
scan.setFilter(filters);
或:
Filter filter1 = new RowFilter(CompareOperator.EQUAL, new RegexStringComparator(".*test7"));
Filter filter2 = new ValueFilter(CompareOperator.EQUAL, new RegexStringComparator(".*spark"));
List<Filter> filterList = new ArrayList<Filter>();
filterList.add(filter1);
filterList.add(filter2);
FilterList filters = new FilterList(filterList);
scan.setFilter(filters);
运行结果:
http://www.test7 f1:host 894spark