hbase的过滤器使用
文章目录
1:过滤器
Hbase 提供了种类丰富的过滤器(filter)来提高数据处理的效率,用户可以通过内置或自定义的过滤器来对数据进行过滤,所有的过滤器都在服务端生效,即谓词下推(predicate push down)。这样可以保证过滤掉的数据不会被传送到客户端,从而减轻网络传输和客户端处理的压力。
命令端操作“scan”和“get”可以执行过滤器。
1:Filter接口和FilterBase抽象类
Filter 接口中定义了过滤器的基本方法,FilterBase 抽象类实现了 Filter 接口。所有内置的过滤器则直接或者间接继承自 FilterBase 抽象类。用户只需要将定义好的过滤器通过 setFilter 方法传递给 Scan 或 put 的实例即可。
2: 过滤器分类
HBase 内置过滤器可以分为三类:分别是比较过滤器,专用过滤器和包装过滤器。
2.1:比较过滤器CompareFilter
RowFilter :基于行键来过滤数据;
FamilyFilterr :基于列族来过滤数据;
QualifierFilterr :基于列限定符(列名)来过滤数据;
ValueFilterr :基于单元格 (cell) 的值来过滤数据;
scan 'testByCrq', FILTER=>"ValueFilter(=,'substring:111')"; //不指定列时全部列的值,也可以指定单独列进行过滤
DependentColumnFilter :指定一个参考列来过滤其他列的过滤器,过滤的原则是基于参考列的时间戳来进行筛选 。
比较器
步骤3中的'binary:中国',这都是比较器。HBase的filter有四种比较器:
(1)二进制比较器:如’binary:abc’,按字典排序跟’abc’进行比较
(2)二进制前缀比较器:如’binaryprefix:abc’,按字典顺序只跟’abc’比较前3个字符
(3)正则表达式比较器:如’regexstring:ab*yz’,按正则表达式匹配以ab开头,以yz结尾的值。这个比较器只能使用=、!=两个比较运算符。
(4)子串比较器:如’substring:abc123’,匹配以abc123开头的值。这个比较器只能使用=、!=两个比较运算符。
比较运算符
1. LESS (<) 小于
2. LESS_OR_EQUAL (<=) 小于等于
3. EQUAL (=) 等于
4. NOT_EQUAL (!=) 不等于
5. GREATER_OR_EQUAL (>=) 大于等于
6. GREATER (>) 大于
2.2:专用过滤器
单列列值过滤器 (SingleColumnValueFilter):基于某列(参考列)的值决定某行数据是否被过滤
单列列值排除器 (SingleColumnValueExcludeFilter)
行键前缀过滤器 (PrefixFilter):基于 RowKey 值决定某行数据是否被过滤。
列名前缀过滤器 (ColumnPrefixFilter):基于列限定符(列名)决定某行数据是否被过滤
分页过滤器 (PageFilter)
时间戳过滤器 (TimestampsFilter)
首次行键过滤器 (FirstKeyOnlyFilter):只扫描每行的第一列,扫描完第一列后就结束对当前行的扫描,并跳转到下一行。
相比于全表扫描,其性能更好,通常用于行数统计的场景,因为如果某一行存在,则行中必然至少有一列
2.3:包装过滤器
SkipFilter过滤器:包装一个过滤器,当被包装的过滤器遇到一个需要过滤的 KeyValue 实例时,则拓展过滤整行数据。下面是一个使用示例:
WhileMatchFilter过滤器: 包装一个过滤器,当被包装的过滤器遇到一个需要过滤的 KeyValue 实例时,则结束本次扫描,返回已经扫描到的结果。也就是只返回一条符合数据
FilterList过滤器:需要多个过滤器共同作用于一次查询的时候,就需要使用 FilterList。FilterList 支持通过构造器或者 addFilter 方法传入多个过滤器。
3:shell使用过滤器操作示例
过滤器使用格式:FILTER => “(filterName(运算符,‘比较器’))”
3.1:比较器和运算符:
比较运算符
1. LESS (<) 小于
2. LESS_OR_EQUAL (<=) 小于等于
3. EQUAL (=) 等于
4. NOT_EQUAL (!=) 不等于
5. GREATER_OR_EQUAL (>=) 大于等于
6. GREATER (>) 大于
比较器:
binary等于比较器,用于值等于
binaryprefix:abc:前缀模糊匹配比较器
substring:abc123:值比较器,包含该值
-
1:ValueFilterr 值过滤器:查询表中任一列值为中国的数据
scan’person’, {FILTER => “ValueFilter(=, ‘binary:中国’)”} -
2:RowFilter:rowkey过滤器
过滤方式是通过rowkey过滤,匹配出rowkey含111的数据
scan ‘testByCrq’, FILTER=>“RowFilter(=,‘substring:111’)” -
3:SingleColumnValueFilter列值过滤器
匹配符合该列的数据
scan ‘tableName’, {FILTER => “(SingleColumnValueFilter(‘info列簇’,‘event_time列名’,=,‘binary:2021-12-16 09:10:06’))”}
ValueFilterr 值过滤器:过滤rk0001行数据值等于中国的。
get 'person', 'rk0001', {FILTER => "ValueFilter(=, 'binary:中国')"}
scan 'person', {COLUMNS => ['info', 'data'], FILTER => "(QualifierFilter(=,'substring:a'))"}
4:java开发过滤器示例
1:单过滤器
// 声明静态配置
static Configuration conf = null;
private static final String ZK_CONNECT_STR = "ip:2181";
static {
conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", ZK_CONNECT_STR);
}
public static void main(String[] args) throws IOException {
HTable table = new HTable(conf, "person".getBytes());
Scan scan = new Scan(Bytes.toBytes("person_zhang_000001"), Bytes.toBytes("person_zhang_000002"));
//前缀过滤器----针对行键
Filter filter = new PrefixFilter(Bytes.toBytes("person"));
//行过滤器 ---针对行键
ByteArrayComparable rowComparator = new BinaryComparator(Bytes.toBytes("person_zhang_000001"));
RowFilter rf = new RowFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, rowComparator);
rf = new RowFilter(CompareFilter.CompareOp.EQUAL , new SubstringComparator("_2016-12-31_"));
//单值过滤器1完整匹配字节数组
new SingleColumnValueFilter("base_info".getBytes(), "name".getBytes(), CompareFilter.CompareOp.EQUAL, "zhangsan".getBytes());
//单值过滤器2 匹配正则表达式
ByteArrayComparable comparator = new RegexStringComparator("zhang.");
new SingleColumnValueFilter("info".getBytes(), "NAME".getBytes(), CompareFilter.CompareOp.EQUAL, comparator);
//单值过滤器3匹配是否包含子串,大小写不敏感
comparator = new SubstringComparator("wu");
new SingleColumnValueFilter("info".getBytes(), "NAME".getBytes(), CompareFilter.CompareOp.EQUAL, comparator);
//键值对元数据过滤-----family过滤----字节数组完整匹配
FamilyFilter ff = new FamilyFilter(CompareFilter.CompareOp.EQUAL ,
new BinaryComparator(Bytes.toBytes("base_info")) //表中不存在inf列簇,过滤结果为空
);
//键值对元数据过滤-----family过滤----字节数组前缀匹配
ff = new FamilyFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryPrefixComparator(Bytes.toBytes("inf")) //表中存在以inf打头的列簇info,过滤结果为该列簇所有行
);
//键值对元数据过滤-----qualifier过滤----字节数组完整匹配
filter = new QualifierFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryComparator(Bytes.toBytes("na")) //表中不存在na列,过滤结果为空
);
filter = new QualifierFilter(
CompareFilter.CompareOp.EQUAL ,
new BinaryPrefixComparator(Bytes.toBytes("na")) //表中存在以na打头的列name,过滤结果为所有行的该列数据
);
//基于列名(即Qualifier)前缀过滤数据的ColumnPrefixFilter
filter = new ColumnPrefixFilter("na".getBytes());
//基于列名(即Qualifier)多个前缀过滤数据的MultipleColumnPrefixFilter
byte[][] prefixes = new byte[][] {Bytes.toBytes("na"), Bytes.toBytes("me")};
filter = new MultipleColumnPrefixFilter(prefixes);
//为查询设置过滤条件
scan.setFilter(filter);
scan.addFamily(Bytes.toBytes("base_info"));
//一行
// Result result = table.get(get);
//多行的数据
ResultScanner scanner = table.getScanner(scan);
table.close();
}
结果集处理:ResultScanner
for(Result r : scanner){
/**
for(KeyValue kv : r.list()){
String family = new String(kv.getFamily());
System.out.println(family);
String qualifier = new String(kv.getQualifier());
System.out.println(qualifier);
System.out.println(new String(kv.getValue()));
}
*/
//直接从result中取到某个特定的value
byte[] value = r.getValue(Bytes.toBytes("base_info"), Bytes.toBytes("name"));
System.out.println(new String(value));
}
2:多个过滤器
通过FilterList添加多个过滤器可以进行使用
FilterList filterList = new FilterList();
filterList.addFilter(singleColumnValueFilter);
filterList.addFilter(pageFilter);
scan.setFilter(filterList);