Hbase过滤器

目录
  • hbase过滤器
    • 过滤器的参数
    • 操作符
    • 六大比较过滤器
      • BinaryComparator
      • BinaryPrefixComparator
      • NullComparator
      • BitComparator
      • RegexStringComparator
      • SubstringComparator
      • 专用过滤器
        • 单列值过滤器:SingleColumnValueFilter
        • 列值排除过滤器:SingleColumnValueExcludeFilter
        • rowkey前缀过滤器:PrefixFilter
        • 分页过滤器PageFilter
    • Bloom Filter(布隆过滤器)
  • hive整合hbase

hbase过滤器

过滤器可以根据列簇、列、版本等更多条件进行过滤。
hbase三维有序(行键、列、版本有序)

过滤器的参数

使用过滤至少需要需要两类参数:一类是抽象的操作符,一类是比较器。

代码及资源:

https://gitee.com/yu-min-guo/hbase-test

操作符

  • LESS <

  • LESS_OR_EQUAL <=

  • EQUAL =

  • NOT_EQUAL <>

  • GREATER_OR_EQUAL >=

  • GREATER >

  • NO_OP 排除所有

六大比较过滤器

BinaryComparator

按字节索引顺序比较指定字节数组,采用Bytes.compareTo(byte[])

BinaryPrefixComparator

通BinaryComparator,只是比较左端前缀的数据是否相同

NullComparator

判断给定的是否为空

BitComparator

按位比较

RegexStringComparator

提供一个正则的比较器,仅支持 EQUAL 和非EQUAL

SubstringComparator

判断提供的子串是否出现在中

专用过滤器

单列值过滤器:SingleColumnValueFilter

SingleColumnValueFilter会返回满足条件的cell所在行的所有cell的值(即会返回一行数据)

通过SingleColumnValueFilter与查询文科班所有学生信息

 @Test
    /**
     * SingleColumnValueFilter
     * 可以指定一个列进行返回
     * 该过滤器会将符合过滤条件的列对应的cell所在的整行数据进行返回
     * 如果某条数据的列不符合条件,则会将整条数据进行过滤
     * 如果数据中不存在指定的列,则默认进行返回
     */
    public void SingleColumnValueFilterTest() throws IOException {
        SingleColumnValueFilter scvf = new SingleColumnValueFilter(
                "cf1".getBytes(),
                "age".getBytes(),
                CompareFilter.CompareOp.GREATER,
                "23".getBytes()
        );

        getFilterResult(scvf);

    }
列值排除过滤器:SingleColumnValueExcludeFilter

与SingleColumnValueFilter相反,会排除掉指定的列,其他的列全部返回

通过SingleColumnValueExcludeFilter与BinaryComparator查询文科一班所有学生信息,最终不返回clazz列

@Test
    /**
     * 过滤文科班的学生
     * SingleColumnValueExcludeFilter 单列值排除过滤器、
     * 与单列值过滤器最大的区别就是结果包不包含比较的列
     *
     */
    public void SingleColumnValueExcludeFilterTest() throws IOException {

        BinaryPrefixComparator bpc = new BinaryPrefixComparator("文科".getBytes());
        SingleColumnValueExcludeFilter scvef = new SingleColumnValueExcludeFilter(
                "cf1".getBytes(),
                "clazz".getBytes(),
                CompareFilter.CompareOp.EQUAL,
                bpc
        );
        getFilterResult(scvef);
    }
rowkey前缀过滤器:PrefixFilter

通过PrefixFilter查询以150010008开头的所有前缀的rowkey

@Test
    /**
     * 过滤出rowkey以 150010088 开头的学生
     * PrefixFilter rowkey前缀过滤器,效率最高
     * 相当于上面的比较器+过滤器
     */
    public void PrefixFilterTest() throws IOException {
        PrefixFilter prefixFilter = new PrefixFilter("150010088".getBytes());

        getFilterResult(prefixFilter);
    }
分页过滤器PageFilter

通过PageFilter查询第三页的数据,每页10条

使用PageFilter分页效率比较低,每次都需要扫描前面的数据,直到扫描到所需要查的数据

可设计一个合理的rowkey来实现分页需求

 @Test
    /**
     * 分页过滤器:PageFilter
     * 获取第四页的数据,每页10条
     *
     * 实际上需要遍历该页前面所有的数据,性能非常低
     */
    public void PageFilter1() throws IOException {
        int page = 4;
        int pageSize = 10;

        // 首先先获取第4页的第一条数据的rk
        int page_first = (page - 1) * pageSize + 1;
        PageFilter pageFilter1 = new PageFilter(page_first);

        Scan scan = new Scan();
        scan.setFilter(pageFilter1);
//        scan.setLimit(40); // PageFilter就相当于setLimit

        String rowkey = null;
        ResultScanner scanner = student.getScanner(scan);
        for (Result rs : scanner) {
            rowkey = Bytes.toString(rs.getRow());
        }

        Scan scan1 = new Scan();
        scan1.withStartRow(rowkey.getBytes());
        PageFilter pageFilter2 = new PageFilter(pageSize);
        scan1.setFilter(pageFilter2);
        ResultScanner scanner2 = student.getScanner(scan1);
        for (Result rs : scanner2) {
            String id = Bytes.toString(rs.getRow());
            String name = Bytes.toString(rs.getValue("info".getBytes(), "name".getBytes()));
            String age = Bytes.toString(rs.getValue("info".getBytes(), "age".getBytes()));
            String gender = Bytes.toString(rs.getValue("info".getBytes(), "gender".getBytes()));
            String clazz = Bytes.toString(rs.getValue("info".getBytes(), "clazz".getBytes()));
            System.out.println(id + "," + name + "," + age + "," + gender + "," + clazz);
        }

    }

Bloom Filter(布隆过滤器)

  • 一个布隆过滤器包含一个二进制向量和n个随机映射函数。
  • 布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
  • 布隆过滤器可以100%确定元素不在集合,但不能100%确定在。
  • 通过BloomFilter快速判断rowkey是否在这个Hfile中,从而过滤掉大部分的Hfile,减少需要扫描的Block。
  • Bloom Filter有两个很重要的参数
    • 哈希函数个数
    • 位数组的大小

HFile 中和 Bloom Filter 相关的Block,
Scanned Block Section(扫描HFile时被读取):Bloom Block
Load-on-open-section(regionServer启动时加载到内存):BloomFilter Meta Block、Bloom Index Block
Bloom Block:Bloom数据块,存储Bloom的位数组
Bloom Index Block:Bloom数据块的索引
BloomFilter Meta Block:从HFile角度看bloom数据块的一些元数据信息,大小个数等等。

HBase中每个HFile都有对应的位数组,KeyValue在写入HFile时会先经过几个hash函数的映射,映射后将对应的数组位改为1,get请求进来之后再进行hash映射,如果在对应数组位上存在0,说明该get请求查询的数据不在该HFile中。
HFile中的Bloom Block中存储的就是上面说得位数组,当HFile很大时,Data Block 就会很多,同时KeyValue也会很多,需要映射入位数组的rowKey也会很多,所以为了保证准确率,位数组就会相应越大,那Bloom Block也会越大,为了解决这个问题就出现了Bloom Index Block,一个HFile中有多个Bloom Block(位数组),根据rowKey拆分,一部分连续的Key使用一个位数组。这样查询rowKey就要先经过Bloom Index Block(在内存中)定位到Bloom Block,再把Bloom Block加载到内存,进行过滤。

hive整合hbase

create external table students_hbase
(
id string,
name string,
age string,
gender string, 
clazz string
)
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties ("hbase.columns.mapping" = "
:key,
info:name,
info:age,
info:gender,
info:clazz
")
tblproperties("hbase.table.name" = "default:student");

你可能感兴趣的:(Hbase过滤器)