HBase Filter 过滤器

HBase 的基本 API,包括增、删、改、查等。查询可以根据 Rowkey 进行 Get 或根据 Rowkey 的范围进行 Scan 扫描。同时提供了更加高级的过滤器(Filter)在 Server 端过滤查询结果,只将满足条件的数据返回给客户端。

过滤器的类型很多,可以分为两大类:比较过滤器和专用过滤器。

比较运算符和比较器

比较过滤器需要两个参数:比较运算符和比较器

比较运算符

在比较过滤器中需要用到比较运算符,HBase 内置以下7种比较运算符

public enum CompareOp {       
    LESS,  // 检查是否小于比较器里的值       
    LESS_OR_EQUAL,  // 检查是否小于或等于比较器里的值       
    EQUAL,  // 检查是否等于比较器里的值       
    NOT_EQUAL, // 检查是否不等于比较器里的值   
    GREATER_OR_EQUAL,  // 检查是否大于或等于比较器里的值   
    GREATER,  // 检查是否大于比较器里的值       
    NO_OP,  // 默认返回false,因此过滤掉所有的数据     
}  

比较器

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

BinaryComparator          // 匹配完整字节数组  
BinaryPrefixComparator    // 匹配字节数组前缀 
BitComparator // 按位执行与、或、异或比较 
NullComparator // 判断当前值是不是 NULL 
RegexStringComparator     // 正则表达式匹配字符串 
SubstringComparator       // 子串匹配,相当于 contains()

比较过滤器

行键过滤器 RowFilter

Scan scan = new Scan(); 

Filter filter = new RowFilter(CompareOp.LESS_OR_EQUAL, 
    new BinaryComparator(Bytes.toBytes("uid-100"))); 
scan.setFilter(filter);

筛选出匹配的所有的行,基于行键(Rowkey)过滤数据,可以执行精确匹配,子字符串匹配或正则表达式匹配,过滤掉不匹配的数据。

一般来说,对 Rowkey 进行范围过滤,可以执行 Scan 的 startKey 和 endKey,RowFilter 可以更精确的过滤。

列族过滤器 FamilyFilter

Scan scan = new Scan(); 

Filter filter = new FamilyFilter(CompareFilter.CompareOp.LESS, 
      new BinaryComparator(Bytes.toBytes("cf-d"))); 
scan.setFilter(filter);

与 RowFilter 类似,区别是比较列族,而不是比较行键。当 HBase 表有多个列族时,可以用来筛选不同列族中的列。

列名过滤器 QualifierFilter

Scan scan = new Scan(); 

Filter filter = new QualifierFilter(CompareFilter.CompareOp.EQUAL, 
    new BinaryComparator(Bytes.toBytes("col-1"))); 
scan.setFilter(filter1);

根据列名进行筛选。

值过滤器 ValueFilter

Scan scan = new Scan(); 

Filter filter = new ValueFilter(CompareFilter.CompareOp.NOT_EQUAL, 
    new SubstringComparator("abc")); 
scan.setFilter(filter);

筛选特定值的单元格,可以与 RegexStringComparator 搭配使用,完成复杂的筛选。

不同的比较器,只能与部分比较运算符搭配,例如 SubstringComparator 只能使用 EQUALNOT_EQUAL

参考列过滤器 DependentColumnFilter

Scan scan = new Scan(); 

Filter filter = new DependentColumnFilter(Bytes.toBytes("cf-d"), 
    Bytes.toBytes("col-1"), 
    "false", 
    CompareOp.EQUAL, 
    new BinaryComparator(Bytes.toBytes("val-1")))) 
scan.setFilter(filter);

一种更复杂的过滤器,不止简单的通过用户指定的信息筛选数据。允许指定一个参考列或引用列,使用参考列控制其他列的过滤。该过滤器会使用参考列的时间戳,并在过滤时包括所有与引用时间戳相同的列。

参考列过滤器相当于一个 ValueFilter 和一个时间戳过滤器的组合。

专用过滤器

单列值过滤器 SingleColumnValueFilter

使用某一列的值,决定一行数据是否被过滤。

Scan scan = new Scan(); 

SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("cf-d"), 
    Bytes.toBytes("col-5"), 
    CompareFilter.CompareOp.NOT_EQUAL, 
    new SubstringComparator("val-1")); 
filter.setFilterIfMissing(true); // 如果不设置为 true,那些不包含指定列的行也会返回 
scan.setFilter(filter);

对于不包含指定列的行数据,通过 setFilterIfMissing() 决定是否返回。

单列值排除器 SingleColumnValueExcludeFilter

继承自 SingleColumnValueFilter,实现的与单列值过滤器相反的语义。

行前缀过滤器 PrefixFilter

Scan scan = new Scan(); 

Filter filter = new PrefixFilter(Bytes.toBytes("row1")); 
scan.setFilter(filter);

基于行键(Rowkey)的前缀过滤行数据。Scan 操作以字典序查找,当行键大于前缀时,Scan 结束。

列前缀过滤器 ColumnPrefixFilter

Scan scan = new Scan(); 

Filter filter = new ColumnPrefixFilter(Bytes.toBytes("col-")); 
scan.setFilter(filter);

通过对列名称的前缀匹配过滤,返回的结果只包含满足过滤器的列。

分页过滤器 PageFilter

byte[] lastRow = null; 
Filter filter = new PageFilter(10); 

while(true) { 
    int rowCount = 0; 
    Scan scan = new Scan(); 
    scan.setFilter(filter); 
    scan.setStartRow(lastRow); 

    ResultScanner resultScanner = table.getScanner(scan); 
    Iterator<Result> resultIterator = resultScanner.iterator(); 
    while (resultIterator.hasNext()) { 
        Result result = resultIterator.next(); 
        // ... 
        lastRow = result.getRow(); // 记录最后一行的rowkey 
        rowCount++; // 记录本页行数 
    } 

    if(rowCount <= 10) { 
        break; 
    } 
}

使用该过滤器,对结果进行按行分野,需要指定 pageSize 参数,控制每页返回的行数,并设置 startRow 多次调用 getScanner(),感觉功能只适用于一些特殊场景,性能也并不高。

行键过滤器 KeyOnlyFilter

KeyOnlyFilter filter = new KeyOnlyFilter(); 
KeyOnlyFilter filter = new KeyOnlyFilter(true);

这个 Filter 只会返回每行的行键+列簇+列,而不返回值(value),对不需要值的应用场景来说,非常实用,减少了值的传递。构造方法可以设置 lenAsValue 参数(默认 false),表示返回时,value 设为原列值的长度。

首次行键过滤器 FirstKeyOnlyFilter

FirstKeyOnlyFilter filter = new FirstKeyOnlyFilter();

这个 Filter 仅仅返回每一行中的第一个 cell 的值,可以用于高效的执行行数统计操作,在扫描到第一个 cell 时,立即跳到下一行数据,性能相比全表扫描得到提升。

包含结束的过滤器 InclusiveStopFilter

Filter filter = new InclusiveStopFilter(Bytes.toBytes("uid-10"));

一般的扫描结果中,设置一个开始行键和一个终止行键,是前闭后开区间,不包含结束行,使用这个过滤器时将结束行加入到结果中。

时间戳过滤器 TimestampsFilter

Filter filter = new TimestampsFilter(Arrays.asList(5L, 10L, 15L)); 
Scan scan1 = new Scan(); 
scan1.setMaxVersions(3) 
scan1.setFilter(filter); 

Scan scan2 = new Scan(); 
scan2.setMaxVersions(3) 
scan2.setFilter(filter); 
scan2.setTimeRange(8, 12);

当需要在扫描结果中对版本进行细粒度控制时,可以使用这个 Filter 传入一个时间戳集合,对时间进行限制,只会返回与指定时间戳相同的版本数据,并且与设置时间戳范围共同使用。

列计数过滤器 ColumnCountGetFilter

Filter filter = new ColumnCountGetFilter(10);

使用这个过滤器,限制每行最多返回多少列。注意当一行的列数达到设定的最大值,过滤器会停止 Scan 操作,所以不适合全表扫描,适合在 Get 方法中使用。

列分页过滤器 ColumnPaginationFilter

Filter filter = new ColumnPaginationFilter(10,5);

与 PageFilter 类似,可以对一行的所有列进行分也,需要传入偏移量 offset 和返回数量 limit。

随机行过滤器 RandomRowFilter

Filter filter = new RandomRowFilter(0.5F);

这个 Filter 可以使结果中包含随机行,参数 chance 取值在 0.0 到 1.0 之间,表示随机取行数的比例,每一行会调用 Random.nextFloat() 与 chance 比较来确定是否被过滤。

附加过滤器

普通过滤器可以提供对返回结果的筛选限制,一些额外的控制可以附加在过滤器上

跳转过滤器 SkipFilter

Scan scan = new Scan(); 
Filter filter1 = new ValueFilter(CompareFilter.CompareOp.NOT_EQUAL, 
    new BinaryComparator(Bytes.toBytes("val-0"))); 
Filter filter2 = new SkipFilter(filter1);

包装了用户的一个过滤器,当过滤器发现某一行的一列需要过滤时,整行数据都被过滤掉。上面的例子是,使用 SkipFilter 和 ValueFilter 组合,获取不等于指定列值的行,同时过滤掉其他不符合条件的行(即只要有一行中一列的值等于“val-0”,就会被过滤)。

全匹配过滤 WhileMatchFilter

Scan scan = new Scan(); 
Filter filter1 = new ValueFilter(CompareFilter.CompareOp.NOT_EQUAL, 
    new BinaryComparator(Bytes.toBytes("val-0"))); 
Filter filter2 = new WhileMatchFilter(filter1);

与SkipFilter 相似,不过当一条数据被过滤掉时,会停止 Scan 操作。可以用来检查全表数据中,是否有某些数据不符合条件。

多种过滤条件的使用方法

通过 FilterList 实例可以提供多个过滤器共同使用的功能。并且可以指定对多个过滤器的过滤结果如何组合。

FilterList 构造函数和方法

FilterList(List<Filter> rowFilters) 
FilterList(Operator operator) 
FilterList(Operator operator, List<Filter> rowFilters) 

void addFilter(Filter filter)

FilterList.Operator 决定了过滤器集合 List<Filter> rowFilters 的组合结果,可选值:

MUST_PASS_ALL // 当所有过滤器都允许包含这个值时,才会加入到结果中
MUST_PASS_ONE // 只需要有一个过滤器允许包含这个值时,就会加入到结果中

代码示例:

Filter filter1 = new ...; 
Filter filter2 = new ...; 
Filter filter3 = new ...; 

FilterList filterList = new FilterList(Arrays.asList(filter1, filter2, filter3)); 

Scan scan = new Scan(); 
scan.setFilter(filterList);

References:
《HBase 权威指南》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 目录: 引言 -- 参数基础 1. 结构(Structural)过滤器--FilterList 2.列值过滤器--...
    磊宝万岁阅读 1,472评论 0 2
  • 一、简介 Hbase:全名Hadoop DataBase,是一种开源的,可伸缩的,严格一致性(并非最终一致性)的分...
    菜鸟小玄阅读 2,362评论 0 12
  • 简介 HBase是高可靠性,高性能,面向列,可伸缩的分布式存储系统,利用HBase技术可在廉价PC Serve...
    九世的猫阅读 2,172评论 1 6
  • 首先,为啥要有过滤器呢? 我们都使用过get()和scan()来获取HBase表中的数据,不过我们在使用过程中会发...
    MasterXiao阅读 1,525评论 0 2
  • 基于列过滤的过滤器 1,ColumnPaginationFilter列分页过滤器:基于列进行分页,需要设置偏移量与...
    Coffeelong阅读 5,241评论 0 7