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 过滤器 (二)

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值