【Hbase学习系列】Hbase常用过滤器使用详解

该系列博文为笔者学习使用hbase时笔记,能使快速入门hbase的一些使用。如发现问题,欢迎批评指正。

章节博文
1【Hbase学习系列】hbase shell常用命令及使用示例
2【Hbase学习系列】Hbase常用过滤器使用详解
3【Hbase学习系列】Hbase加载数据 / 写数据入Hbase

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[]>接口的比较器,源码中其实例化可用子类有:RegexStringComparatorBinaryPrefixComparatorSubstringComparatorBinaryComparatorBigDecimalComparatorBitComparatorLongComparatorNullComparator
各比较器使用方式如下:

  • 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值