hbase過濾器

真好吃啊 發表於 2021-12-06
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");