Hbase-之Client-scan请求过滤器(request filter)

Hbase之Client-scan请求过滤器Filter

0 前言

在Hbase的Client对Hbase的数据进行请求的时候,实际上是可以通过过滤器进行数据的筛选的,Hbase的客户端请求过滤器大致分为5种类,具体详情请参考官方

  • FilterList 【传入过滤器列表,按照MUST_PASS_ONE \MUST_PASS_ALL的规则进行使用】

  • Column Value Filter【为列值维度的过滤,通过特定的value与具体column的值进行匹配】

  • MetaData Filter【为元数据的过滤,可以在扫描之前限定需要扫描的列族、列,避免扫描不需要的数据】

  • RowFilter 【为行过滤器,可以按照rowkey进行匹配】

  • Utility Filter 【为工具型的过滤器,一般用于进行hbase table rowcount操作】

1 FilterList(结构型过滤器)

常用的结构型的过滤器有FilterList,该类的血缘关系如下:

java.lang.Object
	org.apache.hadoop.hbase.filter.Filter
		org.apache.hadoop.hbase.filter.FilterBase
			org.apache.hadoop.hbase.filter.FilterList

FilterList简单使用代码如下:

Connection connection = ConnectionFactory.createConnection();

//创建过滤器列表的实例,可以装在多个实例
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);


//预先准备需要扫描的cf和column-qualifier
byte[] cf = Bytes.toBytes("");
byte[] cq = Bytes.toBytes("");
byte[] value1 = Bytes.toBytes("SuperMan");
byte[] value2 = Bytes.toBytes("BiteMan");


Filter filter1 = TestColumnValueFilter.getSingleColumnValueFilter(cf, cq, value1);
Filter filter2 = TestColumnValueFilter.getSingleColumnValueFilter(cf, cq, value1);

//添加过滤器
filterList.addFilter(filter1);
filterList.addFilter(filter2);

//获取table的实例
Table table = connection.getTable(TableName.valueOf(""));

Scan scan = new Scan();
scan.setFilter(filterList);
scan.setBatch(10000);
ResultScanner scanner = table.getScanner(scan);


//获取scanner中的数据,并进行操作

2 Column Value Filter(列值过滤器)

常用的列值过滤器有ColumnValueFilter,SingleColumnValueFilter,一般列值过滤器还可以配置不同的比较器配合使用;后者作为Hbase2.0.0之后对前者的完善,将row级别的匹配精确到了Cell,2者拥有相同的构造函数,简单的使用单吗如下。

package com.shufang.filter;

import org.apache.hadoop.hbase.CompareOperator;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;


/**
 * 常用的Column-Value相关的过滤器有:
 * @FilterList: 可以用来装在多个过滤器,同时可选择对所有的Filter的配置MUST_PASS_ONE 与 MUST_PASS_ALL之间的过滤规则;
 * @ColumnValueFilter: 返回匹配的Cell,是Hbase在2.0.0的时候对之前版本SingleColumnValueFilter的补充;
 * @SingleColumnValueFilter: 返回匹配到的所有value的所在row的所有数据内容;
 * @ValueFilter: 这个需要在scan的时候预先.addFamily().addColumn(),一般用于简单的查询类似于where$name=name;
 *
 * 一般的列值过滤器都是配合不同的列值比较器进行使用,常用的列值比较器如下。
 * @RegexStringComparator: 正则字符串比较器
 * @SubStringComparator: 子字符串比较器
 * @BinaryPrefixComparator: 二进制前缀比较器
 * @BinaryComparator: 二进制比较器
 * @BinaryComponentComparator: 二进制组建比较器,用特定位置的特定值与Cell进行比较,可以对比ascii和binary数据
 *
 */
public class TestColumnValueFilter {


    public static void main(String[] args) throws IOException {


        Connection connection = ConnectionFactory.createConnection();

        //创建过滤器列表的实例,可以装在多个实例
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);


        //预先准备需要扫描的cf和column-qualifier
        byte[] cf = Bytes.toBytes("");
        byte[] cq = Bytes.toBytes("");
        byte[] value1 = Bytes.toBytes("SuperMan");
        byte[] value2 = Bytes.toBytes("BiteMan");


        /**
         * 对于简单的过滤条件,如:$value = cf:col:value,这种,官方强烈推荐使用ValueFilter,
         * 而不是
         * @ColumnValueFilter and
         * @SingleColumnValueFilter
         * 实例代码如下
         */
        scan.addColumn(cf,cq); //限定扫描额ColumnFamily和Column,避免扫描无关的列
        scan.setFilter(new ValueFilter(CompareOperator.EQUAL,new BinaryComparator(value1)));



        /**
         * 除了对特定value值的过滤支持,ColumnValueFilter还支持另外一种构造参数的过滤方式。
         * @ColumnValueFilter(
         *                  final byte[] family,
         *                  final byte[] qualifier,
         *                  final CompareOperator op,
         *                  final ByteArrayComparable comparator
         *                  TODO 这个参数是一种value的拓展比较方式,可以使用正则、字符串截取进行匹配
         *                  )
         * @regexStringComparator  正则匹配字符串
         * @substringComparator
         */

        RegexStringComparator regexStringComparator = new RegexStringComparator("my."); //所有以my开头的row
        new SingleColumnValueFilter(cf,cq,CompareOperator.EQUAL,regexStringComparator);

        SubstringComparator substringComparator = new SubstringComparator("y val"); //所有包含y val的row,my value会匹配出来
        new SingleColumnValueFilter(cf,cq,CompareOperator.EQUAL,substringComparator);


    }

    /**
     * @SingleColumnValueFilter :对特定value值的所有row进行等值,不等值,或者范围range的筛选
     * CompareOperator.EQUAL
     * CompareOperator.NOT_EQUAL
     * CompareOperator.GREATER
     * @param cf
     * @param cq
     * @param value
     * @return SingleColumnValueFilter
     */
    public static  Filter getSingleColumnValueFilter(byte[] cf,byte[] cq,byte[] value){
        return new SingleColumnValueFilter(cf,cq,CompareOperator.EQUAL,value);
    }


    /**
     * @ColumnValueFilter :在Hbase2.0.0之后,引入了ColumnValueFilter对SingleColumnValueFilter作补充,
     * 仅获取匹配到的value所在的Column的Cell,SingleColumnValueFilter会获取到匹配到的value的所在ROW的所
     * 有数据,包括其它列
     * TODO ColumnValueFilter的构造器参数与SingleColumnValueFilter是保持一致的
     * @param cf
     * @param cq
     * @param value
     * @return ColumnValueFilter
     */
    public static  Filter getColumnValueFilter(byte[] cf,byte[] cq,byte[] value){
        return new ColumnValueFilter(cf,cq,CompareOperator.EQUAL,value);

    }

}

3 MetaData Filter(元数据级别过滤器)

Hbase支持在扫描之从原数据层面进行过滤,避免不必要的扫描资源性能消耗,常用的此类过滤器有FamilyFilter,QualifierFilter,ColumnPrefixFilter,MutipleColumnPrefixFilter,ColumnRangeFilter关于这些过滤器的简单使用代码如下。

package com.shufang.filter;


import com.shufang.charactor01.TestHbaseConnection;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;

/**
 * Hbase的过滤器除了列值过滤器之外还有MetaData相关的过滤器
 *
 * @FamilyFilter:列族过滤器,但是官方建议还是使用scan.addFamily()的方式比较好;
 * @QualifierFilter:列过滤器,但是官方还是建议使用scan.addColumn()的方式会比较好;
 * @ColumnPrefixFilter:列前缀过滤器,将指定前缀的columnQualifier的所有列进行选定匹配;
 * @MutipleColumnPrefixFilter:可以同时匹配多个前缀对应的所有Column的数据,是对上者的一种补充; 具体可以参考以下实例代码
 * @ColumnRangeFilter:用来从大量列中筛选出所需的列;
 */
public class TestHbaseMetaFilter {


    public static void main(String[] args) throws IOException {

        //使用工具创建一个Connection对象
        Connection connection = TestHbaseConnection.getConnection(HBaseConfiguration.create());
        //获取Table的实例
        Table table = connection.getTable(TableName.valueOf("test1"));

        byte[] family = Bytes.toBytes("cf");
        byte[] qualifier = Bytes.toBytes("cq");


        //创建scan,配置family和column
        Scan scan = new Scan();
        //scan.addColumn(family, qualifier);
        scan.setFilter(new FamilyFilter(CompareOperator.EQUAL,new BinaryComparator(family))); //设置列族过滤器
        scan.setFilter(new QualifierFilter(CompareOperator.EQUAL,new BinaryComparator(qualifier))); //设置列过滤器


        /**
         * @ColumnPrefixFilter
         */
        ColumnPrefixFilter abc = new ColumnPrefixFilter(Bytes.toBytes("abc"));
        //scan.setFilter(abc);


        /**
         * @MultipleColumnPrefixFilter
         */
        byte[][] prefixs = {Bytes.toBytes("abc"),Bytes.toBytes("xyz")};
        MultipleColumnPrefixFilter multipleColumnPrefixFilter = new MultipleColumnPrefixFilter(prefixs);
        scan.setFilter(multipleColumnPrefixFilter);

        /**
         * @ColumnRangeFilter:假如Table有100W个列,我只需要[minColumn,macCloumn)区间的列的数据;
         */
        ColumnRangeFilter columnRangeFilter = new ColumnRangeFilter(Bytes.toBytes("minColumn"),
                true, Bytes.toBytes("maxColumn"), false);
        scan.setFilter(columnRangeFilter);


        /**
         * 然后开始扫描结果,并处理获取到的结果
         */
        ResultScanner rs = table.getScanner(scan);
        for (Result r = rs.next(); r != null; r = rs.next()) {
            for (Cell cell : r.rawCells()) {
                //每个Cell就代表Column与Row的交接处的一个单元,一个Cell可能有多个Version的value,默认返回最大时间戳的
                byte[] value = CellUtil.cloneValue(cell);
                //现在就可以处理获取到的结果value了
            }
        }

        rs.close(); //释放内存资源

    }

}

4 RowFilter(行级别的过滤)

在早期的Hbase版本,可以使用scan.setStartRow(),scan.setStopRow() 限定范围,但是这些方法在今后的版本都被标示成过期状态,所以目前有一种过滤器的方式来进行过滤。

对于Row级别的Filter,有2种简单的API可供使用scan.setRowPrefixFilter(Bytes.toBytes("prefix_of_rowkey")),还可以使用scan.setFilter(new RowFilter(comparator_oper.EQUAL,new ByteArrayComparator()))的方式进行筛选,简单使用代码如下。

package com.shufang.filter;

import com.shufang.charactor01.TestHbaseConnection;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.BinaryComparator;
import org.apache.hadoop.hbase.filter.RowFilter;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;

/**
 * 通常Hbase对行的过滤,可以通过startRow与stopRow进行过滤(但是在Hbase2.X后续版本中标示为过时),
 * 但是通过RowFilter也是可以进行过滤操作的!
 *
 * @RowFilter
 */
public class TestRowFilter {
    public static void main(String[] args) throws IOException {

        Connection conn = TestHbaseConnection.getConnection(HBaseConfiguration.create());
        Table table = conn.getTable(TableName.valueOf("test"));


        /**
         * 1、常规的通过scan的原生方法进行过滤
         */
        Scan scan = new Scan();
        //scan.setStartRow()
        //scan.setStopRow()

        /**
         * 2、通过RowFilter进行过滤
         * @RowFilter可以配合@BinaryComponentComparator等比较器进行配合使用,还能扩展过滤功能
         */
        scan.setRowPrefixFilter(Bytes.toBytes("prefix1"));//按照Row的前缀进行过滤匹配
        scan.setFilter(new RowFilter(CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("momoji"))));

        ResultScanner scanner = table.getScanner(scan);
        for (Result r = scanner.next(); r != null ; r= scanner.next()) {

            Cell[] cells = r.rawCells();

            for (Cell cell : cells) {
                //处理cell中的数据
                byte[] value = CellUtil.cloneValue(cell);
                cell.getTimestamp(); //查看Cell对应的版本时间戳。
                //.......
            }
        }

        scanner.close();//释放资源
    }
}

5 Utility Filter(工具型过滤器)

常用的工具型过滤器有FirstKeyOnlyFilter,该过滤器会返回扫描结果的所有row的第一个KV,一般可以用来进行Hbase的rowcount操作,简单代码如下:

package com.shufang.filter;


import com.shufang.charactor01.TestHbaseConnection;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;

import java.io.IOException;

/**
 * Hbase除了列值、row、元数据过滤器之外,还有工具型的过滤器
 *
 * @FirstKeyOnlyFilter:只会返回每行的第一个KV,这里的KV代表一个Cell,在hbase需要进行rowcount的时候很实用
 */
public class TestUtilityFilter {
    public static void main(String[] args) throws IOException {

        Connection conn = TestHbaseConnection.getConnection(HBaseConfiguration.create());


        Table table = conn.getTable(TableName.valueOf(""));
        ResultScanner rs = null;
        try {

            Scan scan = new Scan();
            scan.setFilter(new FirstKeyOnlyFilter());
            rs = table.getScanner(scan);

            //handle the rs with rs.next()
            Long sum = 0l;

            for (Result r = rs.next(); r != null ; r= rs.next()) {
                sum+=1;
                
                Cell[] cells = r.rawCells();
                for (Cell cell : cells) {
                    //处理cell中的数据
                    byte[] value = CellUtil.cloneValue(cell);
                    cell.getTimestamp(); //查看Cell对应的版本时间戳。
                    //.......
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            rs.close();
            table.close();
        }

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值