关于HBase过滤器[转]

过滤数据
到现在为止你了解到HBase拥有灵活的逻辑模式和简单的物理模型,它们允许应用系统的计算工作更接近硬盘和网络,并在这个层次进行优化。设计有效的模式是使用HBase的一个方面,你已经掌握了一堆概念用来做到这点。你可以设计行键以使访问的数据在硬盘上也存放在一起,所以读写操作时可以节省硬盘寻道时间。在读取数据时,你经常需要基于某种标准进行操作,你可以进一步优化数据访问。过滤器就是在这种情况下使用的一种强大的功能。
我们还没有谈到使用过滤器的真实使用场景;一般来说调整表设计就可以优化访问模式。但是有时你已经把表设计调整得尽可能好了,为不同访问模式优化得尽可能好了。当你仍然需要减少返回客户端的数据时,这就是考虑使用过滤器的时候了。有时侯过滤器也被称为下推判断器(push-down predicates),支持你把数据过滤标准从客户端下推到服务器(如图4.16)。这些过滤逻辑在读操作时使用,对返回客户端的数据有影响。这样通过减少网络传输的数据来节省网络IO。但是数据仍然需要从硬盘读进RegionServer,过滤器在RegionServer里发挥作用。因为你有可能在HBase表里存储大量数据,网络IO的节省是有重要意义的,并且先读出全部数据送到客户端再过滤出有用的数据,这种做法开销很大。
图 4.16 在客户端完成数据过滤:从RegionServer把数据读取到客户端,在客户端使用过滤器逻辑处理数据;或者在服务器端完成数据过滤:把过滤逻辑下推到RegionServer,因此减少了在网络上传输到客户端的数据量。实质上过滤器节省了网络IO的开销,有时甚至是硬盘IO的开销。
HBase提供了一个API,你可以用来实现定制过滤器。多个过滤器也可以捆绑在一起使用。可以在读过程最开始的地方,基于行健进行过滤处理。此后,也可以基于HFile读出的KeyValues进行过滤处理。过滤器必须实现HBase Jar包中的Filter接口,或者继承扩展一个实现了该接口的抽象类。我们推荐继承扩展FilterBase抽象类,这样你不需要写样板代码。继承扩展其他诸如CompareFilter类也是一个选择,同样可以正常工作。当读取一行时该接口有下面的方法在多个地方可以调用(顺序如图4.17)。它们总是按照下面描述的顺序来执行:
1 这个方法第一个被调用,基于行健执行过滤:
boolean filterRowKey(byte[] buffer, int offset, int length)
基于这里的逻辑,如果行被过滤掉了(不出现在发送结果集合里)返回true,否则如果发送给客户端则返回false。
2 如果该行没有在上一步被过滤掉,接着调用这个方法处理当前行的每个KeyValue对象:
ReturnCode filterKeyValue(KeyValue v)
这个方法返回一个ReturnCode,这是在Filter接口中定义的一个枚举(enum)类型。返回的ReturnCode判断某个KeyValue对象发生了什么。
3 在第2步过滤KeyValues对象后,接着是这个方法:
void filterRow(List kvs)
这个方法被传入成功通过过滤的KeyValue对象列表。倘若这个方法访问到这个列表,此时你可以在列表里的元素上执行任何转换或运算。
4 如果你选择过滤掉某些行,此时这个方法再一次提供了这么做的机会:
boolean filterRow()
过滤掉考虑中的行,则返回true。
5 你可以在过滤器里构建逻辑来提早停止一次扫描。你可以把该逻辑放进这个方法:
boolean filterAllRemaining()
当你扫描很多行,在行健、列标识符或单元值里查找指定东西时,一旦找到目标,你就不再关心剩下的行了。此时这个方法用起来很方便。这是过滤流程中最后调用的方法。
图 4.17 过滤流程的各个步骤。扫描器对象扫描范围里的每行都会执行这个流程。
另一个有用的方法是reset()。它会重置过滤器,在被应用到整行后由服务器调用。
注意 这个API很强大,但是我们不觉得它是在应用系统里大量使用的。许多情况下,如果模式设计改变了,使用过滤器的需求也会改变。

猜你喜欢

转载自yousky027.iteye.com/blog/1965347