HBase 過濾器 (一)

HBase 過濾器(filters) 提供了非常強大的功能來幫助用戶提高其處理表中數據的效率。用戶不僅可以使用 HBase 中預定義好的過濾器,而且可以實現自定義
的過濾器。



1.1 過濾器介紹 (Introduction to Filters)


HBase 中兩種主要的讀取功能是 Table.get() 和 Table.scan(), 這兩種方法或者直接訪問數據,或者使用起始和結束鍵。可以通過給查詢逐步添加更多的
限制選擇器來限制獲取的數據。這包括 column families, column qualifiers, timestamps 或者 ranges, 以及 version numbers.

這些方法可以幫助用戶控制哪些數據在查詢時被包含其中,但是它們缺少一些細粒度的篩選功能,例如基於正則表達式對行鍵和值進行篩選。Get 和 Scan 兩
個類都支持過濾器基於這樣的原因:無法通過提供的 API 功能選擇需要的行或列的鍵,或者值,但可以通過過濾器實現。其基本接口爲 Filter, 並且 HBase
提供了一系列具體的類,無需編程就可以直接使用。

另一方面,可以擴展 Filter 類來實現自己的需求。所有過濾器實際上應用到服務器端,也稱爲謂詞下推(predicate pushdown)。這樣可以保證被過濾掉的數據
不會被傳送到客戶端。也可以在客戶端代碼中實現過濾功能,但會影響系統性能,因爲這種情況下,服務器端要傳輸更多的數據到客戶端,應儘量避免這種方式。


    ■ Filter 體系結構 (The Filter Hierarchy)
    -------------------------------------------------------------------------------------------------------------------------------------
    在過濾器的體系結構中,最底層的是 Filter abstract class, 並且 FilterBase 類實現了過濾器的空殼和骨架,這使得實際的過濾器類可以避免許多
    重複的結構代碼。
    
    大部分實體過濾器類直接繼承自 FilterBase, 也有一些間接繼承該類。但它們以同樣的方式工作:定義一個要使用過濾器實例,然後把它傳入 Get 或
    Scan 實例:
    
        setFilter(filter)

    在初始化過濾器實例時,需要提供一些參數來設定過濾器的用途。其中有一組特殊的過濾器,它們繼承自 CompareFilter, 需要提供至少兩個特定的參數,
    這兩個參數會被基類用於執行它的任務。

    過濾器可以訪問它們應用的整個行。這意爲着它們可以基於行任何可用的信息來決定該行的命運。這包括 the row key, column qualifiers, column 的
    實際值, timestamps, 等等。


    ■ 比較操作符 (Comparison Operators)
    -------------------------------------------------------------------------------------------------------------------------------------
    因爲基於 CompareFilter 的過濾器比基類 FilterBase 多了一個 compare() 操作,它需要使用一個用戶提供的操作類型來定義比較操作的結果,其值
    列於下表中:

    The possible comparison operators for CompareFilter-based filters
    +-------------------+-----------------------------------------------------------------------------------
    | Operator            | Description
    +-------------------+------------------------------------------------------------------------------------
    | LESS                | Match values less than the provided one.
    +-------------------+------------------------------------------------------------------------------------
    | LESS_OR_EQUAL        | Match values less than or equal to the provided one.
    +-------------------+------------------------------------------------------------------------------------
    | EQUAL                | Do an exact match on the value and the provided one.
    +-------------------+------------------------------------------------------------------------------------
    | NOT_EQUAL            | Include everything that does not match the provided value.
    +-------------------+------------------------------------------------------------------------------------
    | GREATER_OR_EQUAL    | Match values that are equal to or greater than the provided one.
    +-------------------+------------------------------------------------------------------------------------
    | GREATER            | Only include values greater than the provided one.
    +-------------------+------------------------------------------------------------------------------------
    | NO_OP                | Exclude everything.
    +-------------------+------------------------------------------------------------------------------------
    
    當過濾器被應用時,比較操作符可以決定什麼被包含,什麼被排除。這可以幫助用戶篩選數據的一個範圍,一個子集,或一些準確匹配的數據。



    ■ 比較器 (Comparators)
    -------------------------------------------------------------------------------------------------------------------------------------
    第二種需要提供給 CompareFilter 相關類的類型是比較器(comparator), 比較器提供了多種方法來比較不同的鍵和值。比較器都繼承自
    ByteArrayComparable, 它實現了 Java Comparable 接口。如果只想使用 HBase 提供的原生比較器,可以不必過度關注細節,HBase 提供的比較器列於
    下表,這些比較器構造時通常只需要提供一個控制值,這個值將會與 table 中的每個值進行比較。

    The HBase-supplied comparators, used with CompareFilter-based filters
    +---------------------------+-----------------------------------------------------------------------------------------------
    | Comparator                | Description
    +---------------------------+-----------------------------------------------------------------------------------------------
    | LongComparator            | Assumes the given value array is a Java Long number and uses Bytes.toLong() to convert it.
    +---------------------------+-----------------------------------------------------------------------------------------------
    | BinaryComparator            | Uses Bytes.compareTo() to compare the current with the provided value.
    +---------------------------+-----------------------------------------------------------------------------------------------
    | BinaryPrefixComparator    | Similar to the above, but does a left hand, prefix-based match using Bytes.compareTo().
    +---------------------------+-----------------------------------------------------------------------------------------------
    | NullComparator            | Does not compare against an actual value, but checks whether a given one is null, or not null.
    +---------------------------+-----------------------------------------------------------------------------------------------
    | BitComparator                | Performs a bitwise comparison, providing a BitwiseOp enumeration with AND, OR, and XOR operators.
    +---------------------------+-----------------------------------------------------------------------------------------------
    | RegexStringComparator        | Given a regular expression at instantiation, this comparator does a pattern match on the data.
    +---------------------------+-----------------------------------------------------------------------------------------------
    | SubstringComparator        | Treats the value and table data as String instances and performs a contains() check.
    +---------------------------+-----------------------------------------------------------------------------------------------

    
        NOTE:
        ---------------------------------------------------------------------------------------------------------------------------------
        後面的四種比較器 NullComparator, BitComparator, RegexStringComparator, and SubstringComparator, 只能和 EQUAL 和 NOT_EQUAL 操作符
        配合使用,因爲這些比較器的 compareTo() 方法在匹配時返回 0,不匹配時返回 1. 把它們應用到 LESS 或 GREATER 上比較,會產生錯誤的結果。

    通常,每個比較器都有一個帶比較值參數的構造器,換句話說,用戶需要定義一個值用於與每一個 cell 進行比較。有些構造器需要一個 byte[] 作爲
    參數,並通過二進制進行比較,還有一些使用 String 參數進行比較(當需要比較的參數是可讀的有序文本時)。


        NOTE:
        ---------------------------------------------------------------------------------------------------------------------------------
        基於字符串的比較器,RegexStringComparator 和 SubstringComparator, 比基於純字節的比較耗費的成本更高,因爲它們首先需要將一個給定的值
        轉換爲 String, 後續的字符串或正則表達式形式的操作也會增加整個資源耗費成本。




1.2 比較過濾器 (Comparison Filters)
-----------------------------------------------------------------------------------------------------------------------------------------
HBase 提供的第一類過濾器實現是比較過濾器。它們接收比較操作符和比較器實例作爲構造器參數。每個比較過濾器都有一個繼承自 CompareFilter 的相同
簽名的構造器:

    CompareFilter(final CompareOp compareOp, final ByteArrayComparable comparator)

用戶需要提供比較操作符和比較器類來讓過濾器工作。要記住,HBase 過濾器 API 的通用規範的含義是過濾掉信息,被過濾掉的數據不返回給客戶端。過濾
器不是指定要返回的數據,而是在讀取數據時不要返回。

但基於 CompareFilter 的所有過濾器所做的正好相反,它們返回匹配的值、換句話說,在選擇比較操作符時要小心謹慎,它們從服務器返回數據是不同的。
例如如果需要返回大於或等於某個值的數據,就不應該使用 LESS 來忽略不需要的數據,而應當使用 GREATER_OR_EQUAL 來包含想要的數據。


    ■ 行過濾器 (RowFilter)
    -------------------------------------------------------------------------------------------------------------------------------------
    這個過濾器爲用戶提供基於行鍵過濾數據的能力。This filter is used to filter based on the key. It takes an operator (equal, greater, not
    equal, etc) and a byte [] comparator for the row, and column qualifier portions of a key.

    示例:
    
        //Example using a filter to select specific rows
        Scan scan = new Scan();
        scan.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-1"));
        
        // Create filter, while specifying the comparison operator and comparator. Here an exact match is needed.
        Filter filter1 = new RowFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("row-22")));
        scan.setFilter(filter1);
        
        ResultScanner scanner1 = table.getScanner(scan);
        for (Result res : scanner1) {
            System.out.println(res);
        }
        scanner1.close();
        
        //Another filter, this time using a regular expression to match the row keys.
        Filter filter2 = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(".*-.5"));
        scan.setFilter(filter2);
        ResultScanner scanner2 = table.getScanner(scan);
        for (Result res : scanner2) {
            System.out.println(res);
        }
        scanner2.close();
        
        //The third filter uses a substring match approach.
        Filter filter3 = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("-5"));
        scan.setFilter(filter3);
        ResultScanner scanner3 = table.getScanner(scan);
        for (Result res : scanner3) {
            System.out.println(res);
        }
        scanner3.close();

    輸出:
        Adding rows to table...
        Scanning table #1...
        keyvalues={row-1/colfam1:col-1/1427273897619/Put/vlen=7/seqid=0}
        keyvalues={row-10/colfam1:col-1/1427273899185/Put/vlen=8/seqid=0}
        keyvalues={row-100/colfam1:col-1/1427273908651/Put/vlen=9/seqid=0}
        keyvalues={row-11/colfam1:col-1/1427273899343/Put/vlen=8/seqid=0}
        keyvalues={row-12/colfam1:col-1/1427273899496/Put/vlen=8/seqid=0}
        keyvalues={row-13/colfam1:col-1/1427273899643/Put/vlen=8/seqid=0}
        keyvalues={row-14/colfam1:col-1/1427273899785/Put/vlen=8/seqid=0}
        keyvalues={row-15/colfam1:col-1/1427273899925/Put/vlen=8/seqid=0}
        keyvalues={row-16/colfam1:col-1/1427273900064/Put/vlen=8/seqid=0}
        keyvalues={row-17/colfam1:col-1/1427273900202/Put/vlen=8/seqid=0}
        keyvalues={row-18/colfam1:col-1/1427273900343/Put/vlen=8/seqid=0}
        keyvalues={row-19/colfam1:col-1/1427273900484/Put/vlen=8/seqid=0}
        keyvalues={row-2/colfam1:col-1/1427273897860/Put/vlen=7/seqid=0}
        keyvalues={row-20/colfam1:col-1/1427273900623/Put/vlen=8/seqid=0}
        keyvalues={row-21/colfam1:col-1/1427273900757/Put/vlen=8/seqid=0}
        keyvalues={row-22/colfam1:col-1/1427273900881/Put/vlen=8/seqid=0}
        Scanning table #2...
        keyvalues={row-15/colfam1:col-1/1427273899925/Put/vlen=8/seqid=0}
        keyvalues={row-25/colfam1:col-1/1427273901253/Put/vlen=8/seqid=0}
        keyvalues={row-35/colfam1:col-1/1427273902480/Put/vlen=8/seqid=0}
        keyvalues={row-45/colfam1:col-1/1427273903582/Put/vlen=8/seqid=0}
        keyvalues={row-55/colfam1:col-1/1427273904633/Put/vlen=8/seqid=0}
        keyvalues={row-65/colfam1:col-1/1427273905577/Put/vlen=8/seqid=0}
        keyvalues={row-75/colfam1:col-1/1427273906453/Put/vlen=8/seqid=0}
        keyvalues={row-85/colfam1:col-1/1427273907327/Put/vlen=8/seqid=0}
        keyvalues={row-95/colfam1:col-1/1427273908211/Put/vlen=8/seqid=0}
        Scanning table #3...
        keyvalues={row-5/colfam1:col-1/1427273898394/Put/vlen=7/seqid=0}
        keyvalues={row-50/colfam1:col-1/1427273904116/Put/vlen=8/seqid=0}
        keyvalues={row-51/colfam1:col-1/1427273904219/Put/vlen=8/seqid=0}
        keyvalues={row-52/colfam1:col-1/1427273904324/Put/vlen=8/seqid=0}
        keyvalues={row-53/colfam1:col-1/1427273904428/Put/vlen=8/seqid=0}
        keyvalues={row-54/colfam1:col-1/1427273904536/Put/vlen=8/seqid=0}
        keyvalues={row-55/colfam1:col-1/1427273904633/Put/vlen=8/seqid=0}
        keyvalues={row-56/colfam1:col-1/1427273904729/Put/vlen=8/seqid=0}
        keyvalues={row-57/colfam1:col-1/1427273904823/Put/vlen=8/seqid=0}
        keyvalues={row-58/colfam1:col-1/1427273904919/Put/vlen=8/seqid=0}
        keyvalues={row-59/colfam1:col-1/1427273905015/Put/vlen=8/seqid=0}


    ■ 列族過濾器 (FamilyFilter)
    -------------------------------------------------------------------------------------------------------------------------------------
    這個過濾器的工作類似於 RowFilter, 但應用比較到一行的列族上,而不是行鍵上。聯合使用可用的比較操作符和比較器,可以在列族級別過濾出獲取
    數據中包含的數據。
    
    示例: Example using a filter to include only specific column families
        
        // Create filter, while specifying the comparison operator and comparator
        Filter filter1 = new FamilyFilter(CompareFilter.CompareOp.LESS, new BinaryComparator(Bytes.toBytes("colfam3")));
        
        Scan scan = new Scan();
        scan.setFilter(filter1);
        //Scan over table while applying the filter.
        ResultScanner scanner = table.getScanner(scan);
        for (Result result : scanner) {
            System.out.println(result);
        }
        scanner.close();
        
        Get get1 = new Get(Bytes.toBytes("row-5"));
        get1.setFilter(filter1);
        // Get a row while applying the same filter.
        Result result1 = table.get(get1);
        System.out.println("Result of get(): " + result1);
        
        
        Filter filter2 = new FamilyFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("colfam3")));
        //Create a filter on one column family while trying to retrieve another.
        Get get2 = new Get(Bytes.toBytes("row-5"));
        get2.addFamily(Bytes.toBytes("colfam1"));
        get2.setFilter(filter2);
        //Get the same row while applying the new filter, this will return “NONE”.
        Result result2 = table.get(get2);
        System.out.println("Result of get(): " + result2);

    輸出:
        Adding rows to table...
        Scanning table...
        keyvalues={row-1/colfam1:col-1/1427274088598/Put/vlen=7/seqid=0,
        row-1/colfam1:col-2/1427274088615/Put/vlen=7/seqid=0,
        row-1/colfam2:col-1/1427274088598/Put/vlen=7/seqid=0,
        row-1/colfam2:col-2/1427274088615/Put/vlen=7/seqid=0}
        keyvalues={row-10/colfam1:col-1/1427274088673/Put/vlen=8/seqid=0,
        row-10/colfam1:col-2/1427274088675/Put/vlen=8/seqid=0,
        row-10/colfam2:col-1/1427274088673/Put/vlen=8/seqid=0,
        row-10/colfam2:col-2/1427274088675/Put/vlen=8/seqid=0}
        ...
        keyvalues={row-9/colfam1:col-1/1427274088669/Put/vlen=7/seqid=0,
        row-9/colfam1:col-2/1427274088671/Put/vlen=7/seqid=0,
        row-9/colfam2:col-1/1427274088669/Put/vlen=7/seqid=0,
        row-9/colfam2:col-2/1427274088671/Put/vlen=7/seqid=0}
        Result of get(): keyvalues={
        row-5/colfam1:col-1/1427274088652/Put/vlen=7/seqid=0,
        row-5/colfam1:col-2/1427274088654/Put/vlen=7/seqid=0,
        row-5/colfam2:col-1/1427274088652/Put/vlen=7/seqid=0,
        row-5/colfam2:col-2/1427274088654/Put/vlen=7/seqid=0}
        Result of get(): keyvalues=NONE


    ■ 列名過濾器 (QualifierFilter)
    -------------------------------------------------------------------------------------------------------------------------------------
    column qualifier 級別的過濾器,可以從 table 上過濾特定的列:
    
    示例: Example using a filter to include only specific column qualifiers
    
    Filter filter = new QualifierFilter(CompareFilter.CompareOp. LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("col-2")));
    Scan scan = new Scan();
    scan.setFilter(filter);
    ResultScanner scanner = table.getScanner(scan);
    for (Result result : scanner) {
        System.out.println(result);
    }
    scanner.close();
    
    Get get = new Get(Bytes.toBytes("row-5"));
    get.setFilter(filter);
    Result result = table.get(get);
    System.out.println("Result of get(): " + result);

    輸出:
    Adding rows to table...
    Scanning table...
    keyvalues={row-1/colfam1:col-1/1427274739258/Put/vlen=7/seqid=0,
    row-1/colfam1:col-10/1427274739309/Put/vlen=8/seqid=0,
    row-1/colfam1:col-2/1427274739272/Put/vlen=7/seqid=0,
    row-1/colfam2:col-1/1427274739258/Put/vlen=7/seqid=0,
    row-1/colfam2:col-10/1427274739309/Put/vlen=8/seqid=0,
    row-1/colfam2:col-2/1427274739272/Put/vlen=7/seqid=0}
    ...
    keyvalues={row-9/colfam1:col-1/1427274739441/Put/vlen=7/seqid=0,
    row-9/colfam1:col-10/1427274739458/Put/vlen=8/seqid=0,
    row-9/colfam1:col-2/1427274739443/Put/vlen=7/seqid=0,
    row-9/colfam2:col-1/1427274739441/Put/vlen=7/seqid=0,
    row-9/colfam2:col-10/1427274739458/Put/vlen=8/seqid=0,
    row-9/colfam2:col-2/1427274739443/Put/vlen=7/seqid=0}
    Result of get(): keyvalues={
    row-5/colfam1:col-1/1427274739366/Put/vlen=7/seqid=0,
    row-5/colfam1:col-10/1427274739384/Put/vlen=8/seqid=0,
    row-5/colfam1:col-2/1427274739368/Put/vlen=7/seqid=0,
    row-5/colfam2:col-1/1427274739366/Put/vlen=7/seqid=0,
    row-5/colfam2:col-10/1427274739384/Put/vlen=8/seqid=0,
    row-5/colfam2:col-2/1427274739368/Put/vlen=7/seqid=0}


    ■ 值過濾器 (ValueFilter)
    -------------------------------------------------------------------------------------------------------------------------------------
    這個過濾器可用於篩選某個特定值的的列,配合使用 RegexStringComparator,可以使用功能強大的正則表達式語法來篩選。需要注意的是,某些比較器
    正如之前解釋過的那樣,只能使用操作符的一個子集,這裏使用的子串匹配(substring match) 只能與 EQUAL, 或 NOT_EQUAL 操作符聯合使用。
    
    示例: Example using the value based filter
    //Create filter, while specifying the comparison operator and comparator.
    Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL,     new SubstringComparator(".4"));
    Scan scan = new Scan();
    //Set filter for the scan.
    scan.setFilter(filter);
    ResultScanner scanner = table.getScanner(scan);
    for (Result result : scanner) {
        for (Cell cell : result.rawCells()) {
        
            //Print out value to check that filter works.
            System.out.println("Cell: " + cell + ", Value: " +
            Bytes.toString(cell.getValueArray(), cell.getValueOffset(),
            cell.getValueLength()));
        }
    }
    scanner.close();
    
    Get get = new Get(Bytes.toBytes("row-5"));
    //Assign same filter to Get instance.
    get.setFilter(filter);
    Result result = table.get(get);
    
    for (Cell cell : result.rawCells()) {
        System.out.println("Cell: " + cell + ", Value: " +
            Bytes.toString(cell.getValueArray(), cell.getValueOffset(),
            cell.getValueLength()));
    }


    輸出:
    Adding rows to table...
    Results of scan:
    Cell: row-1/colfam1:col-4/1427275408429/Put/vlen=7/seqid=0, Value: val-1.4
    Cell: row-1/colfam2:col-4/1427275408429/Put/vlen=7/seqid=0, Value: val-1.4
    ...
    Cell: row-9/colfam1:col-4/1427275408605/Put/vlen=7/seqid=0, Value: val-9.4
    Cell: row-9/colfam2:col-4/1427275408605/Put/vlen=7/seqid=0, Value: val-9.4
    Result of get:
    Cell: row-5/colfam1:col-4/1427275408527/Put/vlen=7/seqid=0, Value: val-5.4
    Cell: row-5/colfam2:col-4/1427275408527/Put/vlen=7/seqid=0, Value: val-5.4



    ■ 參考列過濾器 (DependentColumnFilter)
    -------------------------------------------------------------------------------------------------------------------------------------
    這是一種更爲複雜的過濾器,不是簡單地基於直接的可用信息過濾掉數據,而是要指定一個依賴的列(dependent column),或者說參考列(reference
    column), 來控制如何過濾其它的列。它使用參考列的時間戳,幷包含所有其它列中具有與之相同時間戳的數據。構造器如下:
    
        DependentColumnFilter(final byte[] family, final byte[] qualifier)
        DependentColumnFilter(final byte[] family, final byte[] qualifier, final boolean dropDependentColumn)
        DependentColumnFilter(final byte[] family, final byte[] qualifier,     final boolean dropDependentColumn,
                            final CompareOp valueCompareOp, final ByteArrayComparable valueComparator)

    由於這個類時基於 CompareFilter 的,因此它提供了更進深入的列選擇,但這個過濾器不是基於列的值過濾的。可以把它理解爲一個 ValueFilter 和一個
    參考時間戳過濾器的組合。用戶可以可選地傳入自己的操作符和比較器對來啓用這一特性。該類提供的構造器,可以忽略操作符和比較器,並忽略按值過濾
    的功能,也就是說整個過濾器值基於參考列的時間戳進行篩選。

    dropDependentColumn 參數用於幫助操作參考列:該參數設爲 false 或 true 決定了參考列可以被返回還是被丟棄。
    
    示例: Example using a filter to include only specific column families
    
    private static void filter(boolean drop, CompareFilter.CompareOp operator, ByteArrayComparable comparator)     throws IOException {
        
        Filter filter;
        if (comparator != null) {
        
            //Create the filter with various options
            filter = new DependentColumnFilter(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5"), drop, operator, comparator);
        } else {
            filter = new DependentColumnFilter(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5"), drop);
        }
        
        Scan scan = new Scan();
        scan.setFilter(filter);
        // scan.setBatch(4); // cause an error
        ResultScanner scanner = table.getScanner(scan);
        for (Result result : scanner) {
            for (Cell cell : result.rawCells()) {
                System.out.println("Cell: " + cell + ", Value: " +
                Bytes.toString(cell.getValueArray(), cell.getValueOffset(),
                cell.getValueLength()));
            }
        }
        scanner.close();
        
        Get get = new Get(Bytes.toBytes("row-5"));
        get.setFilter(filter);
        Result result = table.get(get);
        for (Cell cell : result.rawCells()) {
            System.out.println("Cell: " + cell + ", Value: " +
            Bytes.toString(cell.getValueArray(), cell.getValueOffset(),
            cell.getValueLength()));
        }
    }
    
    public static void main(String[] args) throws IOException {
    
        //Call filter method with various options.
        filter(true, CompareFilter.CompareOp.NO_OP, null);
        filter(false, CompareFilter.CompareOp.NO_OP, null);
        filter(true, CompareFilter.CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("val-5")));
        filter(false, CompareFilter.CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("val-5")));
        filter(true, CompareFilter.CompareOp.EQUAL, new RegexStringComparator(".*\\.5"));
        filter(false, CompareFilter.CompareOp.EQUAL, new RegexStringComparator(".*\\.5"));
    }

        NOTE:
        ---------------------------------------------------------------------------------------------------------------------------------
        這種過濾器與掃描操作的批量處理功能不兼容,也就是 Scan.setBatch() 設置一個大於 0 的值。這個過濾器需要看到整行的數據才能工作,使用
        批處理可能導致取到的數據不包括參考列時間戳,會導致錯誤的結果。

    這個例子不同於之前提到的過濾器,因爲它控制列的版本來得到時間戳相符的結果。服務器端使用隱式的時間戳作爲版本可能導致結果出現波動,主要
    原因是用戶不能保證使用的時間戳精確到毫秒。
    
    filter() 方法使用不同的參數組合調用,展示了內置的值過濾器和 drop 標誌對返回數據集的影響。
    
    輸出:
        Adding rows to table...
        Results of scan:
        Cell: row-1/colfam2:col-5/5/Put/vlen=7/seqid=0, Value: val-1.5
        Cell: row-10/colfam2:col-5/5/Put/vlen=8/seqid=0, Value: val-10.5
        ...
        Cell: row-8/colfam2:col-5/5/Put/vlen=7/seqid=0, Value: val-8.5
        Cell: row-9/colfam2:col-5/5/Put/vlen=7/seqid=0, Value: val-9.5
        Result of get:
        Cell: row-5/colfam2:col-5/5/Put/vlen=7/seqid=0, Value: val-5.5
        Results of scan:
        Cell: row-1/colfam1:col-5/5/Put/vlen=7/seqid=0, Value: val-1.5
        Cell: row-1/colfam2:col-5/5/Put/vlen=7/seqid=0, Value: val-1.5
        Cell: row-9/colfam1:col-5/5/Put/vlen=7/seqid=0, Value: val-9.5
        Cell: row-9/colfam2:col-5/5/Put/vlen=7/seqid=0, Value: val-9.5
        Result of get:
        Cell: row-5/colfam1:col-5/5/Put/vlen=7/seqid=0, Value: val-5.5
        Cell: row-5/colfam2:col-5/5/Put/vlen=7/seqid=0, Value: val-5.5

    設置 dropDependentColumn 爲 true 或 false 得到兩種不同的結果。第一個 scan 和 get 輸出 colfam1 列被忽略,第二部分的輸出它是包含的。
    
    What is this filter good for you might wonder? It is used where applications require client-side timestamps (these could be epoch
    based, or based on some internal global counter) to track dependent updates. Say you insert some kind of transactional data, where
    across the row all fields that are updated, should form some dependent update. In this case the client could set all columns that
    are updated in one mutation to the same timestamp, and when later wanting to show the entity at a certain point in time, get(or scan)
    the row at that time. All modifications from earlier (or later, or exact) changes are then masked out (or included). See for libraries
    on top of HBase that make use of such as schema.
 

 

參考:

HBase 過濾器 (二)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章