【甘道夫】HBase(0.96以上版本)过滤器Filter详解及实例代码

说明:

本文参考官方Ref Guide,Developer API和众多博客,并结合实测代码编写,详细总结HBase的Filter功能,并附上每类Filter的相应代码实现。

本文尽量遵从Ref Guide中“9.4. Client Request Filters”的行文顺序,便于读者对比查看,但内容比官方文档更加详实。

欢迎转载,请注明来源:

http://blog.csdn.net/u010967382/article/details/37653177



目录:

引言 -- 参数基础

1. 结构(Structural)过滤器--FilterList

2.列值过滤器--SingleColumnValueFilter

        2.1.第一种构造函数情况
-- 比较的关键字是字符数组

        2.2.第二种构造函数情况
-- 比较的关键字是比较器ByteArrayComparable

3.键值元数据

        3.1. 基于列族过滤数据的FamilyFilter

        3.2. 基于限定符Qualifier(列)过滤数据的QualifierFilter

        3.3. 基于列名(即Qualifier)前缀过滤数据的ColumnPrefixFilter

        3.4. 基于多个列名(即Qualifier)前缀过滤数据的MultipleColumnPrefixFilter

        3.5. 基于列范围(不是行范围)过滤数据ColumnRangeFilter

4. RowKey

5. Utility--FirstKeyOnlyFilter

6. 取得查询结果



引言 -- 参数基础

有两个参数类在各类Filter中经常出现,统一介绍下:

(1)比较运算符 CompareFilter.CompareOp

比较运算符用于定义比较关系,可以有以下几类值供选择:

  1. EQUAL                                  相等
  2. GREATER                              大于
  3. GREATER_OR_EQUAL           大于等于
  4. LESS                                      小于
  5. LESS_OR_EQUAL                  小于等于
  6. NOT_EQUAL                        不等于

(2)比较器  ByteArrayComparable

通过比较器可以实现多样化目标匹配效果,比较器有以下子类可以使用:

  1. BinaryComparator       
           匹配完整字节数组
  2. BinaryPrefixComparator     匹配字节数组前缀
  3. BitComparator
  4. NullComparator
  5. RegexStringComparator    正则表达式匹配
  6. SubstringComparator        子串匹配


1. 结构(Structural)过滤器--FilterList

FilterList 代表一个过滤器链,它可以包含一组即将应用于目标数据集的过滤器,过滤器间具有“与” FilterList.Operator.MUST_PASS_ALL 和“或” FilterList.Operator.MUST_PASS_ONE 关系。

官网实例代码,两个“或”关系的过滤器的写法:

FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ONE);   //数据只要满足一组过滤器中的一个就可以

SingleColumnValueFilter filter1 = new SingleColumnValueFilter(

cf,

column,

CompareOp.EQUAL,

Bytes.toBytes("my value")

);

list.add(filter1);

SingleColumnValueFilter filter2 = new SingleColumnValueFilter(

cf,

column,

CompareOp.EQUAL,

Bytes.toBytes("my other value")

);

list.add(filter2);

Scan scan = new Scan();

scan.setFilter(list);


2. 列值过滤器--SingleColumnValueFilter

SingleColumnValueFilter 用于测试列值相等
(CompareOp.EQUAL ), 不等 (CompareOp.NOT_EQUAL),或单侧范围 (e.g., CompareOp.GREATER)

构造函数:

(1)比较的关键字是一个字符数组

SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareFilter.CompareOp compareOp, byte[] value)

(2)比较的关键字是一个比较器(比较器下一小节做介绍)

SingleColumnValueFilter(byte[] family, byte[] qualifier, CompareFilter.CompareOp compareOp, ByteArrayComparable comparator)


2.1.第一种构造函数情况 -- 比较的关键字是字符数组

官网示例代码,检查列值和字符串‘my value‘ 相等:

SingleColumnValueFilter filter = new SingleColumnValueFilter(

cf,

column,

CompareOp.EQUAL,

Bytes.toBytes("my value")

);

scan.setFilter(filter);

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);

SingleColumnValueFilter filter = new SingleColumnValueFilter(

Bytes.toBytes("patentinfo"),

Bytes.toBytes("CREATE_TIME"),

CompareOp.EQUAL,

Bytes.toBytes("2013-06-08")

);

filterList.addFilter(filter);

Scan scan = new Scan();

scan.setFilter(filterList);

ResultScanner rs = table.getScanner(scan);

for (Result r : rs) {

System.out.println("Scan: " + r);

}

table.close();

注意:还是大写问题,HBase的列名必须大写!


2.2.第二种构造函数情况 -- 比较的关键字是比较器ByteArrayComparable

该章节主要是针对SingleColumnValueFilter的第二种构造函数使用情况做了一些举例:

(1)支持值比较的正则表达式 -- RegexStringComparator

官网示例代码

RegexStringComparator comp = new RegexStringComparator("my.");   //任意以my打头的值

SingleColumnValueFilter filter = new SingleColumnValueFilter(

cf,

column,

CompareOp.EQUAL,

comp

);

scan.setFilter(filter);

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);

RegexStringComparator comp = new RegexStringComparator("2013-06-1.");

SingleColumnValueFilter filter = new SingleColumnValueFilter(

Bytes.toBytes("patentinfo"),

Bytes.toBytes("CREATE_TIME"),

CompareOp.EQUAL,

comp

);

filterList.addFilter(filter);

Scan scan = new Scan();

scan.setFilter(filterList);

ResultScanner rs = table.getScanner(scan);

for (Result r : rs) {

System.out.println("Scan: " + r);

}

table.close();

(2)检测一个子串是否存在于值中(大小写不敏感) -- SubstringComparator

官网示例代码:

SubstringComparator comp = new SubstringComparator("y val");   // looking for ‘my value‘

SingleColumnValueFilter filter = new SingleColumnValueFilter(

cf,

column,

CompareOp.EQUAL,

comp

);

scan.setFilter(filter);

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);

//        RegexStringComparator comp = new RegexStringComparator("2013-06-1.");

SubstringComparator comp = new SubstringComparator("2013-06-1");

SingleColumnValueFilter filter = new SingleColumnValueFilter(

Bytes.toBytes("patentinfo"),

Bytes.toBytes("CREATE_TIME"),

CompareOp.EQUAL,

comp

);

filterList.addFilter(filter);

Scan scan = new Scan();

scan.setFilter(filterList);

ResultScanner rs = table.getScanner(scan);

for (Result r : rs) {

System.out.println("Scan: " + r);

}

table.close();

(3)BinaryComparator

二进制比较器,用得较少,有需要请自行查阅官网:http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/BinaryComparator.html

(4)BinaryPrefixComparator

二进制前缀比较器,用得较少,有需要请自行查阅官网:http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/BinaryPrefixComparator.html


3. 键值元数据

由于HBase 采用键值对保存内部数据,键值元数据过滤器评估一行的键(ColumnFamily:Qualifiers)是否存在 ,
对应前节所述值的情况。


3.1. 基于列族过滤数据的FamilyFilter

构造函数:

FamilyFilter(CompareFilter.CompareOp familyCompareOp, ByteArrayComparable familyComparator)

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

/**

         * FamilyFilter构造函数中第二个参数是ByteArrayComparable类型

         * ByteArrayComparable类参见“引言-参数基础”章节

         * 下面仅以最可能用到的BinaryComparator、BinaryPrefixComparator举例:

*/

FamilyFilter ff = new FamilyFilter(

CompareFilter.CompareOp.EQUAL ,

new BinaryComparator(Bytes.toBytes("pat"))   //表中不存在pat列族,过滤结果为空

);

FamilyFilter ff1 = new FamilyFilter(

CompareFilter.CompareOp.EQUAL ,

new BinaryPrefixComparator(Bytes.toBytes("pat"))   //表中存在以pat打头的列族patentinfo,过滤结果为该列族所有行

);

Scan scan = new Scan();

scan.setFilter(ff1);

ResultScanner rs = table.getScanner(scan);

注意:

  1. 如果希望查找的是一个已知的列族,则使用 scan.addFamily(family)  比使用过滤器效率更高;
  2. 由于目前HBase对多列族支持不完善,所以该过滤器目前用途不大。

3.2. 基于限定符Qualifier(列)过滤数据的QualifierFilter

构造函数:

QualifierFilter(CompareFilter.CompareOp op, ByteArrayComparable qualifierComparator)

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

/**

* QualifierFilter构造函数中第二个参数是ByteArrayComparable类型

* ByteArrayComparable类有以下子类可以使用:

* *******************************************

* BinaryComparator  匹配完整字节数组,

* BinaryPrefixComparator  匹配开始的部分字节数组,

* BitComparator,

* NullComparator,

* RegexStringComparator,   正则表达式匹配

* SubstringComparator

* *******************************************

* 下面仅以最可能用到的BinaryComparator、BinaryPrefixComparator举例:

*/

QualifierFilter ff = new QualifierFilter(

CompareFilter.CompareOp.EQUAL ,

new BinaryComparator(Bytes.toBytes("belong"))   //表中不存在belong列,过滤结果为空

);

QualifierFilter ff1 = new QualifierFilter(

CompareFilter.CompareOp.EQUAL ,

new BinaryPrefixComparator(Bytes.toBytes("BELONG"))   //表中存在以BELONG打头的列BELONG_SITE,过滤结果为所有行的该列数据

);

Scan scan = new Scan();

scan.setFilter(ff1);

ResultScanner rs = table.getScanner(scan);

说明:

  1. 一旦涉及到列(Qualifier),HBase就只认大写字母了!
  2. 该过滤器应该比FamilyFilter更常用!

3.3. 基于列名(即Qualifier)前缀过滤数据的ColumnPrefixFilter
 ( 该功能用QualifierFilter也能实现 )

构造函数:

ColumnPrefixFilter(byte[] prefix)

注意:

一个列名是可以出现在多个列族中的,该过滤器将返回所有列族中匹配的列。

官网示例代码,查找所有"abc"打头的列:

HTableInterface t = ...;

byte[] row = ...;

byte[] family = ...;

byte[] prefix = Bytes.toBytes("abc");

Scan scan = new Scan(row, row); // (optional) limit to one row

scan.addFamily(family); // (optional) limit to one family

Filter f = new ColumnPrefixFilter(prefix);

scan.setFilter(f);

scan.setBatch(10); // set this if there could be many columns returned

ResultScanner rs = t.getScanner(scan);

for (Result r = rs.next(); r != null; r = rs.next()) {

for (KeyValue kv : r.raw()) {

// each kv represents a column

}

}

rs.close();

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

//返回所有行中以BELONG打头的列的数据

ColumnPrefixFilter ff1 = new ColumnPrefixFilter(Bytes.toBytes("BELONG"));

Scan scan = new Scan();

scan.setFilter(ff1);

ResultScanner rs = table.getScanner(scan);


3.4. 基于多个列名(即Qualifier)前缀过滤数据的MultipleColumnPrefixFilter

说明:

MultipleColumnPrefixFilter 和 ColumnPrefixFilter 行为差不多,但可以指定多个前缀。

官方示例代码,查找所有"abc"或"xyz"打头的列:

HTableInterface t = ...;

byte[] row = ...;

byte[] family = ...;

byte[][] prefixes = new byte[][] {Bytes.toBytes("abc"), Bytes.toBytes("xyz")};

Scan scan = new Scan(row, row); // (optional) limit to one row

scan.addFamily(family); // (optional) limit to one family

Filter f = new MultipleColumnPrefixFilter(prefixes);

scan.setFilter(f);

scan.setBatch(10); // set this if there could be many columns returned

ResultScanner rs = t.getScanner(scan);

for (Result r = rs.next(); r != null; r = rs.next()) {

for (KeyValue kv : r.raw()) {

// each kv represents a column

}

}

rs.close();

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

byte[][] prefixes = new byte[][] {Bytes.toBytes("BELONG"), Bytes.toBytes("CREATE")};

//返回所有行中以BELONG或者CREATE打头的列的数据

MultipleColumnPrefixFilter ff = new MultipleColumnPrefixFilter(prefixes);

Scan scan = new Scan();

scan.setFilter(ff);

ResultScanner rs = table.getScanner(scan);


3.5. 基于列范围(不是行范围)过滤数据ColumnRangeFilter

说明:

  1. 可用于获得一个范围的列,例如,如果你的一行中有百万个列,但是你只希望查看列名为bbbb到dddd的范围
  2. 该方法从 HBase 0.92 版本开始引入
  3. 一个列名是可以出现在多个列族中的,该过滤器将返回所有列族中匹配的列

构造函数:

ColumnRangeFilter(byte[] minColumn, boolean minColumnInclusive, byte[] maxColumn, boolean maxColumnInclusive)

参数解释:

  • minColumn - 列范围的最小值,如果为空,则没有下限;
  • minColumnInclusive - 列范围是否包含minColumn ;
  • maxColumn - 列范围最大值,如果为空,则没有上限;
  • maxColumnInclusive - 列范围是否包含maxColumn 。

官网示例代码,查找列名在"bbbb"到"dddd"范围的数据:

HTableInterface t = ...;

byte[] row = ...;

byte[] family = ...;

byte[] startColumn = Bytes.toBytes("bbbb");

byte[] endColumn = Bytes.toBytes("bbdd");

Scan scan = new Scan(row, row); // (optional) limit to one row

scan.addFamily(family); // (optional) limit to one family

Filter f = new ColumnRangeFilter(startColumn, true, endColumn, true);

scan.setFilter(f);

scan.setBatch(10); // set this if there could be many columns returned

ResultScanner rs = t.getScanner(scan);

for (Result r = rs.next(); r != null; r = rs.next()) {

for (KeyValue kv : r.raw()) {

// each kv represents a column

}

}

rs.close();

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

byte[] startColumn = Bytes.toBytes("C");

byte[] endColumn = Bytes.toBytes("D");

//返回所有列中从C到D打头的范围的数据,实际返回类似CREATOR、CREATE_TIME、CHANNEL_CODE等列的数据

ColumnRangeFilter ff = new ColumnRangeFilter(startColumn, true, endColumn, true);

Scan scan = new Scan();

scan.setFilter(ff);

ResultScanner rs = table.getScanner(scan);



4. RowKey

当需要根据行键特征查找一个范围的行数据时,使用Scan的startRow和stopRow会更高效,但是,startRow和stopRow只能匹配行键的开始字符,而不能匹配中间包含的字符:

byte[] startColumn = Bytes.toBytes("aaa");

byte[] endColumn = Bytes.toBytes("bbb");

Scan scan = new Scan(startColumn,endColumn);

当需要针对行键进行更复杂的过滤时,可以使用RowFilter:

构造函数:

RowFilter(CompareFilter.CompareOp rowCompareOp, ByteArrayComparable rowComparator)

参数解释参见“引言-参数基础”章节。

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

/**

* rowkey格式为:创建日期_发布日期_ID_TITLE

* 目标:查找  发布日期  为  2013-07-16  的数据

*/

RowFilter rf = new RowFilter(

CompareFilter.CompareOp.EQUAL ,

new SubstringComparator("_2013-07-16_")

);

Scan scan = new Scan();

scan.setFilter(rf);

ResultScanner rs = table.getScanner(scan);

注意:

测试过程中尝试通过组合使用两个RowFilter(CompareFilter.CompareOp参数分别为GREATER_OR_EQUALLESS_OR_EQUAL),和SubstringComparator,过滤找出指定发布时间范围内的数据,但结果比较意外,不是预想的数据,估计比较运算符GREATER_OR_EQUALLESS_OR_EQUAL和比较器SubstringComparator组合使用效果不太好,慎用。


5. Utility--FirstKeyOnlyFilter

该过滤器仅仅返回每一行中的第一个cell的值,可以用于高效的执行行数统计操作。

估计实战意义不大。

构造函数:

public FirstKeyOnlyFilter()

个人实测代码:

HTable table = HBaseDAO.getHTable("147patents");

FirstKeyOnlyFilter fkof = new FirstKeyOnlyFilter();

Scan scan = new Scan();

scan.setFilter(fkof);

ResultScanner rs = table.getScanner(scan);


6. 取得查询结果

无论是官网的Ref Guide还是网上流传的大部分博客中,输出查询结果的代码都是:

for (Result r = rs.next(); r != null; r = rs.next()) {

for (KeyValue kv : r.raw()) {

// each kv represents a column

}

}

但查看最新的API可知Result实例的raw()方法已经不建议使用了:

raw() Deprecated. as of 0.96, use rawCells()

0.96以后版本正确的获取结果代码如下:

for (Result r : rs) {

for (Cell cell : r.rawCells()) {

System.out.println(

"Rowkey : "+Bytes.toString(r.getRow())+

"Familiy:Quilifier : "+Bytes.toString(CellUtil.cloneQualifier(cell))+

"Value : "+Bytes.toString(CellUtil.cloneValue(cell))

);

}

}

【甘道夫】HBase(0.96以上版本)过滤器Filter详解及实例代码

时间: 2024-10-31 12:46:34

【甘道夫】HBase(0.96以上版本)过滤器Filter详解及实例代码的相关文章

HBase(0.96以上版本)过滤器Filter详解及实例代码

说明: 本文参考官方Ref Guide,Developer API和众多博客,并结合实测代码编写,详细总结HBase的Filter功能,并附上每类Filter的相应代码实现. 本文尽量遵从Ref Guide中"9.4. Client Request Filters"的行文顺序,便于读者对比查看,但内容比官方文档更加详实. ***2014年7月18日更新,新增PageFilter和SkipFilter.*** 目录: 引言 -- 参数基础 1. 结构(Structural)过滤器--Fi

【甘道夫】HBase基本数据操作详解【完整版,绝对精品】

引言 之前详细写了一篇HBase过滤器的文章,今天把基础的表和数据相关操作补上. 本文档参考最新(截止2014年7月16日)的官方Ref Guide.Developer API编写. 所有代码均基于"hbase 0.96.2-hadoop2"版本编写,均实测通过. 欢迎转载,请注明来源: http://blog.csdn.net/u010967382/article/details/37878701 概述 对于建表,和RDBMS类似,HBase也有namespace的概念,可以指定表空

【甘道夫】Hadoop2.2.0环境使用Sqoop-1.4.4将Oracle11g数据导入HBase0.96,并自动生成组合行键

目的: 使用Sqoop将Oracle中的数据导入到HBase中,并自动生成组合行键! 环境: Hadoop2.2.0 Hbase0.96 sqoop-1.4.4.bin__hadoop-2.0.4-alpha.tar.gz Oracle11g jdk1.7 Ubuntu14 Server 这里关于环境吐槽一句: 最新版本的Sqoop1.99.3功能太弱,只支持导入数据到HDFS,没有别的任何选项,太土了!(如有不同意见欢迎讨论给出解决方案) 命令: sqoop import --connect

【甘道夫】使用sqoop-1.4.4.bin__hadoop-2.0.4-alpha将Oracle11g数据导入HBase0.96

环境: Hadoop2.2.0 Hbase0.96 sqoop-1.4.4.bin__hadoop-2.0.4-alpha.tar.gz Oracle11g jdk1.7 Ubuntu14 Server 这里关于环境吐槽一句: 最新版本的Sqoop1.99.3功能太弱,只支持导入数据到HDFS,没有别的任何选项,太土了!(如有不同意见欢迎讨论给出解决方案) 命令: sqoop import --connect jdbc:oracle:thin:@192.168.0.147:1521:ORCLGB

【甘道夫】Eclipse+Maven搭建HBase开发环境及HBaseDAO代码示例

环境: Win764bit Eclipse Version: Kepler Service Release 1 java version "1.7.0_40" 第一步:Eclipse中新建Maven项目,编辑pom.xml并更新下载jar包 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&qu

【甘道夫】Win7环境下Eclipse连接Hadoop2.2.0

准备: 确保hadoop2.2.0集群正常运行 1.eclipse中建立java工程,导入hadoop2.2.0相关jar包 2.在src根目录下拷入log4j.properties,通过log4j查看详细日志 log4j.rootLogger=debug, stdout, R log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLa

【甘道夫】HBase开发环境搭建过程中可能遇到的异常:No FileSystem for scheme: hdfs

异常: 2014-02-24 12:15:48,507 WARN  [Thread-2] util.DynamicClassLoader (DynamicClassLoader.java:<init>(106)) - Failed to identify the fs of dir hdfs://fulonghadoop/hbase/lib, ignored java.io.IOException: No FileSystem for scheme: hdfs 解决: 在pom文件中加入: &

【甘道夫】用贝叶斯文本分类测试打过1329-3.patch的Mahout0.9 on Hadoop2.2.0

引言 接前一篇文章<[甘道夫]Mahout0.9 打patch使其支持 Hadoop2.2.0> http://blog.csdn.net/u010967382/article/details/39088035, 为Mahout0.9打过Patch编译成功后,使用贝叶斯文本分类来测试Mahout0.9对Hadoop2.2.0的兼容性. 欢迎转载,转载请注明出处: http://blog.csdn.net/u010967382/article/details/39088285 步骤一:将20ne

【甘道夫】Hadoop2.2.0 NN HA详细配置+Client透明性试验【完整版】

引言: 前面转载过一篇团队兄弟[伊利丹]写的NN HA实验记录,我也基于他的环境实验了NN HA对于Client的透明性. 本篇文章记录的是亲自配置NN HA的详细全过程,以及全面测试HA对客户端访问透明性的全过程,希望对大家有帮助. 实验环境: Hadoop2.2.0的4节点集群,ZK节点3个(ZK节点数最好为奇数个),hosts文件和各节点角色分配如下: hosts: 192.168.66.91 master 192.168.66.92 slave1 192.168.66.93 slave2