FuzzyRowFilter 的说明和使用
FuzzyRowFilter是模糊查询row(指定rowkey里面部分值可以不是前缀,指定符合前缀的可以用PrefixFilter)的filter,能够在scan的时候快速向前扫描。
举例:存到hbase里面的数据,很多时候rowkey是由多个部分组合而成,而各个部分又是固定长度。比如userId_actionId_year_month组成key,userId 是固定的4字节,actionId 是2字节,year 是4字节,month 是2字节。
如果想查某个action类型比如99,并且在1月份的所有用户出来,
那么我们需要获取的数据是rowkey为 “????_99_????_01” “?”代表任意值(一个字节长)。
如果没有FuzzyRowFilter 的话,那么需要整表扫描过滤出来符合条件的数据,如果有FuzzyRowFilter 的话,在某些场景下会快很多了。它的原理是以上面的为例:符合????_99_????_01的rowkey ,起始是0000_99_0000_01 ,结束是1111_99_1111_01,根据这个条件就可以限制起始范围,另外在扫描的过程中可以从一个key跳到下一个key去,因为满足条件的key必须符合 ????_99_????_01,所以那么不符合这个条件的row不会进行匹配,直接跳过,seek到下一个符合条件的row去,这样就加快了查找速度。
FuzzyRowFilter 的使用:
FuzzyRowFilter rowFilter = new FuzzyRowFilter(
Arrays.asList(
new Pair<byte[], byte[]>(
Bytes.toBytesBinary(“\x00\x00\x00\00_99_\x00\x00\x00\00_01”),
new byte[] {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0})));
Scan scan = new Scan();
scan.setFilter(rowFilter);
重点是 pair (row key, fuzzy info) :
(1)Bytes.toBytesBinary(“\x00\x00\x00\00_99_\x00\x00\x00\00_01”) 是 rowkey(0000_99_0000_01),
(2)new byte[] {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0} 是fuzzy info(mask用),1的意思是该位置对应的值不用匹配,0表示该位置的值必须要匹配。
所以指定的符合条件的rowkey是 ????_99_????_01 “?”代表任意值
FuzzyRowFilter有自己的局限性,比如????_99_????_01,这里表示rowkey必须要有15个字节长,如果比这个短,也会匹配上(导致使用场景有限制)。另外它性能提升的关键在于能够跳过多少数据,如果跳过的数据量多,那么提升越明显。
目前我们的hbase-0.94-adh3u3版本已经有这个Filter,该版本测试进入尾声,进入最后的回归,马上就会发布,该版本的release note详见http://baike.corp.taobao.com/index.php/0.94-adh3u3
Reference:
https://issues.apache.org/jira/browse/HBASE-6509
Implement fast-forwarding FuzzyRowFilter to allow filtering rows e.g. by “???alex?b”
HBase FuzzyRowFilter: Alternative to Secondary Indexes
http://blog.sematext.com/2012/08/09/consider-using-fuzzyrowfilter-when-in-need-for-secondary-indexes-in-hbase/