过滤器简介

HBase过滤器提供了非常强大的特性来帮助用户提高其处理表中数据的效率。

HBase中两种主要的数据读取函数是get和scan,它们都支持直接访问数据和通过指定起止行键访问数据的功能。可以再查询中添加更多的限制条件来减少查询得到的数据量,这些限制可以使指定列族、列、时间戳以及版本号。

所有的过滤器都在服务端生效,叫做谓词下推(predicate push down),这样可以保证被过滤掉的数据不会被传送到客户端。也可以在客户端代码中实现过滤的功能(但会影响系统性能),因为这种情况下服务器端需要传输更多的数据到客户端,用户应当尽量避免这种情况。

过滤器的层次结构

在过滤器层次结构的最底层是Filter和FilterBase抽象类,它们实现了过滤器的空壳和骨架,这使得实际的过滤器类可以避免许多重复的结构代码。

过滤器可以作用于用户插入的整行数据,所以用户可以基于任意可用的信息来决定如何处理这一行。这些信息包括行键、列名、实际的列值和时间戳等。

比较运算符

以为继承自CompareFilter的过滤器比基类FilterBase多了一个compare方法,它需要使用传入参数定义比较操作的过程。

操作

描述

LESS

匹配小于设定值的值

LESS_OR_EQUAL

匹配小于或等于设定值的值

EQUAL

匹配等于设置值的值

NOT_EQUAL

匹配与设定值不相等的值

GREATER_OR_EQUAL

匹配大于或等于设定值的值

GREATER

匹配大于设定值的值

NO_OP

排除一切值

比较器

CompareFilter所需要的第二类类型是比较器(comparator),比较器提供了多种方法来比较不同的键值。比较器都继承自WritableByteArrayComparable,WritableByteArrayComparable实现了Writable和Comparable接口。

比较器

描述

BinaryComparator

使用Bytes.compareTo比较当前值与阈值

BinaryPrefixComparator

使用Bytes.compareTo进行匹配,但是是从左端开始前缀匹配

NullComparator

不做匹配,只判断当前值是不是null

BitComparator

通过BitwiseOp类提供的按位与(AND)\或(OR)\异或(XOR)操作执行位级比较

RegexStringComparator

根据一个正则表达式,在实例化这个比较器的时候去匹配表中的数据

SubstringComparator

把阈值和表中数据当做string实例,同时通过contains操作匹配字符串

注意:后面的三种比较器,BitComparator、RegexStringComparator、SubstringComparator,只能与EQUAL和NOT_EQUAL运算符搭配使用,因为这些比较器的compareTo方法匹配时返回0,不匹配时返回1.如果和LESS和GREATER运算符搭配使用,会产生错误。

基于字符串的的比较器,比如RegexStringComparator和SubstringComparator,比基于字节的比较器更慢,更消耗资源。因为每次比较时它们都需要将给定的值转化为string。截取字符串子串和正则式的处理也需要花费额外的时间。

比较过滤器

每个比较过滤器的构造方法都有一个从CompareFilter继承来的签名方法

public CompareFilter(final CompareOp compareOp,

      final ByteArrayComparable comparator) {

      this.compareOp = compareOp;

      this.comparator = comparator;

  }

注意:HBase中过滤器本来的目的是为了筛掉无用的信息。被过滤掉的信息不会被传送到客户端。过滤器不能用来指定用户需要哪些信息,而是在读取数据的过程中不返回用户不想要的信息。

正好相反,所有基于CompareFilter的过滤处理过程与上面所描述的恰好相反,它们返回匹配的值。用户需要根据过滤器的不同规则来小心地挑选过滤器。

HBase连接代码

private static String addr="node233,node232,node231";
private static String port="2181";
Logger logger = Logger.getLogger(getClass()); private static Connection connection; public static void getConnection(){
Configuration conf = HBaseConfiguration.create(); conf.set("hbase.zookeeper.quorum",addr);
conf.set("hbase.zookeeper.property.clientPort", port);
try {
connection = ConnectionFactory.createConnection(conf);
} catch (IOException e) {
e.printStackTrace();
}
} /*
* 关闭连接
*
*/
public static void close() {
/**
* close connection
**/
if (connection != null) {
try {
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) {
getConnection();
try {
columnPaginationFilterTest();
} catch (IOException e) {
e.printStackTrace();
}
close();
}

1.行过滤器(RowFilter)

行过滤器是基于行键来过滤数据

/**
* 对rowkey检索
* @throws IOException
*/
public static void rowFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase")); Scan scan = new Scan();
scan.addColumn(Bytes.toBytes("userInfo"), Bytes.toBytes("id"));
Filter filter = new RowFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("110115199402265244")));
scan.setFilter(filter); ResultScanner scanner = table.getScanner(scan);
//keyvalues={110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0}
for (Result result : scanner) {
System.out.println(result);
}
scanner.close(); System.out.println("==============filter2===============");
//检索出rowkey以244结尾的
Filter filter2 = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(".*.244") );
scan.setFilter(filter2);
ResultScanner scanner2 = table.getScanner(scan);
for (Result result : scanner2) {
System.out.println(result);
}
scanner2.close(); System.out.println("==============filter3===============");
//检索出rowkey包含244的
Filter filter3 = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("244"));
scan.setFilter(filter3);
ResultScanner scanner3 = table.getScanner(scan);
for (Result result : scanner3) {
Cell[] cells = result.rawCells();
for (Cell cell : cells) {
System.out.println(Bytes.toString(CellUtil.cloneValue(cell)));
}
System.out.println(result);
}
scanner3.close();
}

  

2.列族过滤器(FamilyFilter)

这个过滤器与行过滤器相似,不过它是通过比较列族而不是比较行键来返回结果的。通过使用不同组合的运算符和比较器,用户可以在列族一级筛选所需要的数据。

/**
* 列族过滤器
* @throws IOException
*/
public static void faimlyFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase"));
Filter filter = new FamilyFilter(CompareOp.LESS, new BinaryComparator(Bytes.toBytes("userInfo")));
Scan scan = new Scan();
scan.setFilter(filter);
//使用过滤器扫描表
ResultScanner scanner = table.getScanner(scan);
//keyvalues={110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0}
//keyvalues={110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0}
for (Result result : scanner) {
System.out.println(result);
}
scanner.close();
System.out.println("============get==============");
//使用相同过滤器获取一行数据
//Result of get():keyvalues={110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0}
Get get = new Get(Bytes.toBytes("110115199402265244"));
get.setFilter(filter);
Result result = table.get(get);
System.out.println("Result of get():" + result);
System.out.println("============filter=============");
//在一个列族上创建过滤器,同时获取另一行数据
//使用新的过滤器获取同一行数据,此时返回结果为NONE
//Result of get():keyvalues=NONE
Filter filter2 = new FamilyFilter(CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("userInfo1")));
Get get2 = new Get(Bytes.toBytes("110115199402265244"));
get2.addFamily(Bytes.toBytes("tag"));
get2.setFilter(filter2);
Result result2 = table.get(get2);
System.out.println("Result of get():" + result2);
}

3.列名过滤器(QualifierFilter)

/**
* 列名过滤器(QualifierFilter)
* @throws IOException
*/
public static void qualifiterFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase"));
Filter filter = new QualifierFilter(CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("basic_222")));
Scan scan = new Scan();
scan.setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
//keyvalues={110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0}
for (Result result : scanner) {
System.out.println(result);
}
scanner.close();
Get get = new Get(Bytes.toBytes("110115199402265244"));
get.setFilter(filter);
Result result = table.get(get);
//Result of get():keyvalues={110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0}
System.out.println("Result of get():" + result);
}

4.值过滤器(ValueFilter)

筛选某个特定值的单元格。

/**
* 值过滤器
* @throws IOException
*/
public static void valueFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase"));
Filter filter = new ValueFilter(CompareOp.EQUAL, new SubstringComparator("si"));
Scan scan = new Scan();
scan.setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
//CELL: 110115199402265245/userInfo:name/1535527529043/Put/vlen=4/seqid=0,Value:lisi
for (Result result : scanner) {
for (Cell cell : result.rawCells()) {
System.out.println("CELL: " + cell + ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}
scanner.close();
System.out.println("===============get===============");
Get get = new Get(Bytes.toBytes("110115199402265245"));
get.setFilter(filter);
Result result = table.get(get);
for (Cell cell : result.rawCells()) {
System.out.println("CELL: " + cell + ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}

5.参考列过滤器(DependentColumnFilter)

此过滤器允许用户指定一个参考列或是引用列,并使用参考列控制其他列的过滤。参考列过滤器使用参考列的时间戳,并在过滤时包括所有与引用时间戳相同的列。

构造方法:

public DependentColumnFilter(final byte [] family, final byte[] qualifier,
final boolean dropDependentColumn, final CompareOp valueCompareOp,
final ByteArrayComparable valueComparator)
public DependentColumnFilter(final byte [] family, final byte [] qualifier)
public DependentColumnFilter(final byte [] family, final byte [] qualifier,
final boolean dropDependentColumn)

可以传入比较运算符和基准值来启用ValueFilter的功能。这个过滤器的构造函数默认允许用户在所有列上忽略运算符和比较器,以及屏蔽按值筛选的功能,也就是说整个过滤器只基于参考列的时间戳进行筛选。

dropDependentColumn可以帮助用户操作参选列:该参数设为false或true决定了参考列可以被返回还是被丢弃。

/**
* 参考列过滤器
* @throws IOException
*/
public static void dependentColumnFilterTest() throws IOException {
//CELL: 110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0,Value:223
filter(true, CompareOp.NO_OP, null);
System.out.println("----------filter(false, CompareOp.NO_OP, null);--------");
//CELL: 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0,Value:"张三"
//CELL: 110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0,Value:223
//CELL: 110115199402265245/userInfo:name/1535527529043/Put/vlen=4/seqid=0,Value:lisi
filter(false, CompareOp.NO_OP, null);
System.out.println("----------filter(true, CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes(\"row\")));--------");
//CELL: 110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0,Value:223
filter(true, CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("li")));
System.out.println("----------filter(false, CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes(\"row\")));--------");
//CELL: 110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0,Value:223
//CELL: 110115199402265245/userInfo:name/1535527529043/Put/vlen=4/seqid=0,Value:lisi
filter(false, CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.toBytes("li")));
System.out.println("----------filter(true, CompareOp.EQUAL, new RegexStringComparator(\".*.si\"));--------");
//CELL: 110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0,Value:223
filter(true, CompareOp.EQUAL, new RegexStringComparator(".*.si"));
System.out.println("----------filter(false, CompareOp.EQUAL, new RegexStringComparator(\".*.si\"));--------");
//CELL: 110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0,Value:223
//CELL: 110115199402265245/userInfo:name/1535527529043/Put/vlen=4/seqid=0,Value:lisi
filter(false, CompareOp.EQUAL, new RegexStringComparator(".*.si"));
}
public static void filter(boolean drop, CompareOp operator, ByteArrayComparable comparator) throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase"));
Filter filter;
if (null != comparator) {
filter = new DependentColumnFilter(Bytes.toBytes("userInfo"), Bytes.toBytes("name"),
drop, operator, comparator);
} else {
filter = new DependentColumnFilter(Bytes.toBytes("userInfo"), Bytes.toBytes("name"), drop);
}
Scan scan = new Scan();
scan.setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
for (Cell cell : result.rawCells()) {
System.out.println("CELL: " + cell + ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}
}

这种过滤器与扫描操作的批量处理功能不兼容。过滤器需要查看整行数据来决定那些数据被过滤,使用批量处理可能会导致取到的数据中不包括参考列,因此结果有错。

专用过滤器

HBase提供的专用过滤器直接继承自FilterBase,同时用于更特定的使用场景。其中的一些过滤器只能做行筛选,因此只适用于扫描操作。

1.单列值过滤器(SingleColumnValueFilter)

用一列的值决定是否一行数据被过滤

构造方法

public SingleColumnValueFilter(final byte [] family, final byte [] qualifier,
final CompareOp compareOp, final byte[] value)
public SingleColumnValueFilter(final byte [] family, final byte [] qualifier,
final CompareOp compareOp, final ByteArrayComparable comparator)

辅助方法微调过滤

public boolean getFilterIfMissing()
public void setFilterIfMissing (boolean filterIfMissing)
public boolean getLatestVersionOnly()
public void setLatestVersionOnly(boolean latestVersionOnly)

setFilterIfMissing:当参考列不存在时如何处理这一行。默认的这一行是被抱哈年结果中的,如果想要过滤掉这些行,可以使用setFilterIfMissing(true)来过滤,在这样设置后,所有不包含参考列的行都可以被过滤掉。

注意:用户在扫描时必须包括参考列,用户使用类似于addColumn的方法把参考列添加到查询中。如果没有这么做,也就是说扫描结果中没有包括参考列,那么结果可能为空或包含所有行,具体结果根据setFilterIfMissing的设定值来返回

setLatestVersionOnly:可以改变过滤器的行为,默认值为true,此时过滤器只检查参考列的最新版本,如果设为false,会检查所有版本。

/**
* 单列值过滤
* @throws IOException
* 排除掉符合条件的
*/
public static void singleColumnValueFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase")); SingleColumnValueFilter filter =
new SingleColumnValueFilter(Bytes.toBytes("userInfo"), Bytes.toBytes("name"),
CompareOp.NOT_EQUAL, new SubstringComparator("si"));
filter.setFilterIfMissing(true); /**
* CELL: 110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0,Value:222
CELL: 110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0,Value:110115199402265244
CELL: 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0,Value:"张三"
CELL: 110115199402265244/userInfo:row/1535525614718/Put/vlen=5/seqid=0,Value:row-1
*/
Scan scan = new Scan();
scan.setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
for (Cell cell : result.rawCells()) {
System.out.println("CELL: " + cell + ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}
scanner.close(); /**
* Result of get():keyvalues={110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0, 110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0, 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0, 110115199402265244/userInfo:row/1535525614718/Put/vlen=5/seqid=0}
CELL: 110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0,Value:222
CELL: 110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0,Value:110115199402265244
CELL: 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0,Value:"张三"
CELL: 110115199402265244/userInfo:row/1535525614718/Put/vlen=5/seqid=0,Value:row-1
*/
Get get = new Get(Bytes.toBytes("110115199402265244"));
get.setFilter(filter);
Result result = table.get(get);
System.out.println("Result of get():" + result);
for (Cell cell : result.rawCells()) {
System.out.println("CELL: " + cell + ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}

2.单列排除过滤器(SingleColumnValueExcludeFilter)

单列排除过滤器继承自SingleColumnValueFilter,参考列不被包括到结果中。用户可以使用与之前相同的特性和方法来控制过滤器的工作,唯一的不同是,客户端Result实例中用户永远不会获得作为检查目标的参考列。

3.前缀过滤器(PrefixFilter)

在构造当前过滤器时传入一个前缀,所有与前缀匹配的行都会被返回到客户端。在扫描操作中非常有用。

/**
* 前缀过滤器
* @throws IOException
* 返回满足条件的
*/
public static void prefixFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase")); Filter filter = new PrefixFilter(Bytes.toBytes("110"));
Scan scan = new Scan();
scan.setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
/**
* CELL: 110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0,Value:222
CELL: 110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0,Value:110115199402265244
CELL: 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0,Value:"张三"
CELL: 110115199402265244/userInfo:row/1535525614718/Put/vlen=5/seqid=0,Value:row-1
CELL: 110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0,Value:223
CELL: 110115199402265245/userInfo:id/1535524869900/Put/vlen=18/seqid=0,Value:110115199402265245
CELL: 110115199402265245/userInfo:name/1535527529043/Put/vlen=4/seqid=0,Value:lisi
CELL: 110115199402265245/userInfo:row/1535525622873/Put/vlen=5/seqid=0,Value:row-2
*/
for (Result result : scanner) {
for (Cell cell : result.rawCells()) {
System.out.println("CELL: " + cell + ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}
scanner.close();
}

扫描操作以字典序查找,当遇到比前缀大的行时,扫描操作就结束了。通过与起始行配合使用,过滤器的扫描性能大大提高,原因是当它发现后面的行不符合要求时会全部跳过。

4.分页过滤器(PageFilter)

用户可以使用这个过滤器对结果按行分页。当用户创建当前过滤器实例时需要指定pageSize参数,这个参数可以控制每页返回的行数。

注意:在物理上分离的服务器中并行执行过滤操作时,需要注意以下几个事项。

在不同的region服务器上并行执行的过滤器不能共享它们现在的状态和边界,因此,每个过滤器都会在完成扫描前获取pageCount行的结果,这种情况使得分页过滤器可能失效,极有可能返回的比所需要的多。最终客户端在合并结果时可以选择返回所有结果,也可以使用API根据需求筛选结果。

客户端代码会记录本次扫描的最后一行,并在下一次获取数据时把记录的上次扫描的最后一行设为这次扫描的起始行,同时保留相同的过滤属性,然后依次进行迭代。

分页时对依次返回的行数设定了严格的限制,依次扫描所覆盖的行数很可能是多于分页大小的,一旦这种情况发生,过滤器有一种机制通知region服务器停止扫描。

/**
* 分页过滤器
* @throws IOException
*/
public static void pageFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("socialSecurity"));
int pageCount = 10;
Filter filter = new PageFilter(pageCount);
int totalRows = 0;
byte[] lastRow = null;
while(true) {
Scan scan = new Scan();
scan.setFilter(filter);
if (lastRow != null) {
byte[] startRow = Bytes.add(lastRow, new byte[0]);
System.out.println("start row:" + Bytes.toStringBinary(startRow));
scan.setStartRow(startRow);
}
ResultScanner scanner = table.getScanner(scan);
int localRows = 0;
Result result;
while ((result = scanner.next()) != null) {
System.out.println(localRows++ + ": " + result);
totalRows++;
lastRow = result.getRow();
}
scanner.close();
if (localRows == 0 || localRows < pageCount) {
break;
}
}
System.out.println("total rows: " + totalRows);
}

HBase中的行键是按字典序排列的,因此返回的结果也是如此排序的,并且起始行是被包括在结果中的。用户需要拼接一个零字节(一个长度为零的字节数组)到之前的行键,这样可以保证最后返回的行在本轮扫描时不被包括。当重置扫描的边界时,零字节是最可靠的方式,因为零字节是最小的增幅。即使有一行的行键正好与之前一行加零字节相同,在这一轮循环时也不会有问题,因为起始行在扫描时是被包括在内的。

5.行键过滤器(KeyOnlyFilter)

在一些应用中只需要将结果中KeyValue实例的键返回,而不需要返回实际的数据。KeyOnlyFilter提供了可以修改扫描出的列和单元格的功能。这个过滤器通过KeyValue.convertToKeyOnly(boolean)方法帮助调用只返回键不返回值。

public KeyOnlyFilter(boolean lenAsVal)

这个过滤器的构造函数中需要一个叫lenAsVal的布尔参数。这个参数会被传入convertToKeyOnly方法中,它可以控制KeyValue实例中值的处理。默认值为false,设置为false时,值被设为长度为0的字节数组,设置为true时,值被设为原值长度的字节数组。

6.首次行键过滤器(FirstKeyOnlyFilter)

如果用户需要访问一行中的第一列,则这种过滤器可以满足需求。这种过滤器通常在行数统计(row counter)的应用场景中使用,这种场景只需要检查这一行是否存在。在列式存储数据库中如果某一行存在,则行中必然有列。

由于列也按字典序排列,因此其他可能用到的场景是按照时间先后生成列名,这样最旧的就会排在最前面,因此时间戳最久的列会最先被检索到。

这个类使用了过滤器框架提供的另一个优化特性:它在检查完第一列之后会通知region服务器结束对当前行的扫描,并跳到下一行,与全表扫描相比,其性能得到了提升。

7.包含结束的过滤器(InclusiveStopFilter)

扫描操作中的开始行被包含到结果中,但终止行被排除在外。使用这个过滤器,也可以将终止行包含在内。

/**
* 包含结束的过滤器
* @throws IOException
*/
public static void inclusiveStopFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase")); Filter filter = new InclusiveStopFilter(Bytes.toBytes("110115199402265245"));
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes("110115199402265244"));
//keyvalues={110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0, 110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0, 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0, 110115199402265244/userInfo:row/1535525614718/Put/vlen=5/seqid=0}
//keyvalues={110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0, 110115199402265245/userInfo:id/1535524869900/Put/vlen=18/seqid=0, 110115199402265245/userInfo:name/1535527529043/Put/vlen=4/seqid=0, 110115199402265245/userInfo:row/1535525622873/Put/vlen=5/seqid=0}
scan.setFilter(filter); //keyvalues={110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0, 110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0, 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0, 110115199402265244/userInfo:row/1535525614718/Put/vlen=5/seqid=0}
//scan.setStopRow(Bytes.toBytes("110115199402265245"));
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
System.out.println(result);
}
scanner.close();
}

  

8.时间戳过滤器(TimestampFilter)

当用户需要在扫描结果中对版本进行细粒度的控制时,这个过滤器可以满足需求。用户需要传入一个装载了时间戳的List实例

public TimestampsFilter(List<Long> timestamps)

一个版本(version)是指一个列在一个特定时间的值,因此用一个时间戳(timestamp)来表示。当过滤器请求一系列的时间戳时,它会找到与其中时间戳精确匹配的列版本。

/**
* 时间戳过滤器
* @throws IOException
* 如果多个时间戳对应一行,则只返回一行
* 如果指定了同一列的不同时间戳,则返回新的时间戳的数据
*/
public static void timestampsFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase"));
List<Long> ts = new ArrayList<Long>();
ts.add(new Long(1535080434895L));
ts.add(new Long(1535527096150L));
ts.add(new Long(1535079590454L));
Filter filter = new TimestampsFilter(ts); /**
* keyvalues={110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0}
keyvalues={110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0, 110115199402265245/userInfo:name/1535079590454/Put/vlen=4/seqid=0}
*/
Scan scan = new Scan();
scan.setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
for (Cell cell : result.rawCells()) {
System.out.println("CELL: " + cell + ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}
scanner.close(); System.out.println("==========scan2==========");
/**
* keyvalues={110115199402265244/tag:basic_222/1535079521796/Put/vlen=3/seqid=0, 110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0, 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0, 110115199402265244/userInfo:row/1535525614718/Put/vlen=5/seqid=0}
keyvalues={110115199402265245/tag:basic_223/1535079590454/Put/vlen=3/seqid=0, 110115199402265245/userInfo:id/1535524869900/Put/vlen=18/seqid=0, 110115199402265245/userInfo:name/1535527529043/Put/vlen=4/seqid=0, 110115199402265245/userInfo:row/1535525622873/Put/vlen=5/seqid=0}
*/
Scan scan2 = new Scan();
scan.setFilter(filter);
scan.setTimeRange(1535080434895L, 1535527096149L);
ResultScanner scanner2 = table.getScanner(scan2);
for (Result result : scanner2) {
for (Cell cell : result.rawCells()) {
System.out.println("CELL: " + cell + ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
}
}
scanner2.close();
}

9.列计数过滤器(ColumnCountGetFilter)

可以使用这个过滤器来限制每行最多取回多少列。

public ColumnCountGetFilter(final int n)

当一行的列数达到设定的最大值时,这个过滤器会停止整个扫描操作,所以它不太适合扫描操作,反而比较适合在get方法中使用。

10.列分页过滤器(ColumnPaginationFilter)

与PageFilter相似,这个过滤器可以对一行的所有列进行分页。构造器如下

public ColumnPaginationFilter(final int limit, final int offset)

它将跳过所有偏移量小于offset的列,并包括之后所有偏移量在limit之前的列。

/**
* 列分页过滤器
* @throws IOException
*/
public static void columnPaginationFilterTest() throws IOException {
Table table = connection.getTable(TableName.valueOf("test_hbase"));
//返回两列,从列索引1(第二列)开始
Filter filter = new ColumnPaginationFilter(2, 1);
/**
* keyvalues={110115199402265244/userInfo:id/1535524861515/Put/vlen=18/seqid=0, 110115199402265244/userInfo:name/1535527096150/Put/vlen=8/seqid=0}
keyvalues={110115199402265245/userInfo:id/1535524869900/Put/vlen=18/seqid=0, 110115199402265245/userInfo:name/1535527529043/Put/vlen=4/seqid=0}
*/
Scan scan = new Scan();
scan.setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
System.out.println(result);
}
scanner.close();
}

 

11.列前缀过滤器(ColumnPrefixFilter)

类似于PrefixFilter,这个过滤器通过对列名称进行前缀匹配过滤。

public ColumnPrefixFilter(final byte [] prefix)

12.随机行过滤器(RandomRowFilter)

可以让结果中包含随机行。构造器如下

public RandomRowFilter(float chance)

在过滤器内部会使用java方法Random.nextFloat()来决定一行是否被过滤,使用这个方法的结果会与用户设定的chance进行比较。如果用户为chance赋一个负值会导致所有结果都被过滤掉,相反,如果chance大于1.0则结果集中包含所有行。

HBase-过滤器(各种过滤器及代码实现)的更多相关文章

  1. HBase笔记6 过滤器

    过滤器 过滤器是GET或者SCAN时过滤结果用的,相当于SQL的where语句 HBase中的过滤器创建后会被序列化,然后分发到各个region server中,region server会还原过滤器 ...

  2. 在Wireshrak中使用过滤器——捕获过滤器

    过滤器可以让你找出你所希望进行分析的数据包.简单来说,一个过滤器就是定义了一定条件,用来包含或者排除数据包的表达式.如果你不希望看到一些数据包,你可以写一恶搞过滤器来屏蔽它们.如果你希望只看到某些数据 ...

  3. 笨鸟先飞之ASP.NET MVC系列之过滤器(01过滤器简介)

    过滤器 什么是过滤器? 过滤器(Filter) 主要的作用大致可以理解为把我们的附加逻辑注入到MVC框架的请求处理. 在ASP.NET MVC的请求处理中一种有19个管道事件分别是 BeginRequ ...

  4. MVC过滤器:过滤器执行顺序

    如果某个Action过滤器运用了多种过滤器,那么过滤器的执行顺序是如何呢? 规则一:不同类型的过滤器有一个先后顺序 即执行顺序是:授权过滤器->动作过滤器->结果过滤器->异常过滤器 ...

  5. Django---MTV和MVC的了解,Django的模版语言变量和逻辑,常见的模板语言过滤器,自定义过滤器,CSRF了解,Django的母版(继承extends,块block,组件include,静态文件的加载load static),自定义simple_tag和inclusion_tag

    Django---MTV和MVC的了解,Django的模版语言变量和逻辑,常见的模板语言过滤器,自定义过滤器,CSRF了解,Django的母版(继承extends,块block,组件include,静 ...

  6. HBase学习之路 (十一)HBase的协过滤器

    协处理器—Coprocessor 1. 起源 Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执 行求和.计数.排序等操作.比如,在旧版本的(<0.92)Hba ...

  7. Django内置过滤器详解附代码附效果图--附全部内置过滤器帮助文档

    前言 基本环境 Django版本:1.11.8 Python版本:3.6 OS: win10 x64 本文摘要 提供了常用的Django内置过滤器的详细介绍,包括过滤器的功能.语法.代码和效果示例. ...

  8. ASP.NET Core 使用过滤器移除重复代码

    USING ACTIONFILTERS TO REMOVE DUPLICATED CODE ASP.NET Core 的过滤器可以让我们在请求管道的特定状态之前或之后运行一些代码.因此如果我们的 ac ...

  9. hbase 多个过滤器组合(列表)

    使用FilterList要保证过滤器的顺序需要使用List<Filter> private static void mutilFilterData() throws IOException ...

  10. HBase shell scan 过滤器用法总结

    比较器: 前面例子中的regexstring:2014-11-08.*.binary:\x00\x00\x00\x05,这都是比较器.HBase的filter有四种比较器: (1)二进制比较器:如’b ...

随机推荐

  1. Android无线测试之—UiAutomator UiSelector API介绍之三

    节点关系介绍 每一个布局文件都是一个严格的层次结构布局文件,只有对层次结构非常的了解,才能更好的搜索定位我们需要的主键元素 一.XML文档节点关系介绍 备注:查看节点关系主要使用UiAutomatro ...

  2. 《从零开始学Swift》学习笔记(Day 17)——Swift中数组集合

    原创文章,欢迎转载.转载请注明:关东升的博客 数组(Array)是一串有序的由相同类型元素构成的集合.数组中的集合元素是有序的,可以重复出现. 声明一个Array类型的时候可以使用下面的语句之一. v ...

  3. 1624 取余最长路(set)

    1624 取余最长路 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱 ...

  4. TFS二次开发-基线文件管理器(4)-标签的创建

    上一节已经完成了源码文件的读取,如果要将已经选择的文件保存为一个标签(Lable).在VS我们只能对一个目录做标签,非常的不方便.如果用下面的方法,将选择的文件路径保存为一个List在打标签,就非常的 ...

  5. 机器重启 查看crontab执行历史记录crontab没有执行

    Sep 17 19:01:01 d run-parts(/etc/cron.hourly)[8452]: finished 0anacronSep 17 19:10:01 d CROND[9059]: ...

  6. 明文post密码

    w 作者:余天升链接:https://www.zhihu.com/question/20306241/answer/14696464 看到上面几位的回答,我真心觉得,当前信息安全保护的意识过于低下,连 ...

  7. 【转】Power System 中基于 VIOS 的虚拟以太网实现

    基于 VIOS 的虚拟以太网适配器的工作原理和配置实现 本文对 Power 系统中基于 VIOS 的虚拟以太网适配器(Virtual Ethernet Adapter)的工作原理.基本配置选项和配置步 ...

  8. python基础知识回顾[1]

    1.声明变量 # 声明一个变量name用来存储一个字符串'apollo' name = 'apollo' # 声明一个变量age用来存储一个数字20 age = 20 # 在控制台打印变量name中存 ...

  9. 博客没内容可写了怎么办?找BD!

    博客写了一段时间可能会感觉没内容可以写了,或者说同一个领域的内容写多了感觉有点千篇一律,这时要考虑扩展自己的写作领域,怎么去扩展呢?利用关键词工具可以衍生很多长尾词,当然这个有点牵强,有点为优化而优化 ...

  10. MCU与FPGA通信

    1.MCU启动FPGA相应功能模块 通过译码器选择相应的功能模块,调用实现功能. 2.MCU与FPGA串口通信 SPI协议简单.可靠.易实现,速度快,推荐使用SPI.SPI为四线机制,包含MOSI.M ...