hbase:hbase查询及scanfilter的使用
1.Scan
HBase常用的查看数据方式有scan和get,get是一种特殊的scan,get是scan的startrow和endrow等于同一个值的特殊情况。
hbase的rowkey是按照B+树的形式存放的,所以查找一个具体的rowkey速度是非常快的,所以查询数据的时候一般都会设置scan的startrow和endrow,这样可以缩小查找的范围,所以rowkey的设计在hbase里面是极为重要的。
可以这样讲,hbase里面的查询数据只有scan一种形式,就是在B+树里面查找rowkey,而scan就是对rowkey的一种顺序”扫”。
查看一下scan里面对rowkey的条件筛选,只有startrow和endrow这一组,所以可以理解为sql条件里面的”>”和”<”。
hbase的rowkey是按照顺序排列的,所以在设计rowkey的时候尽量将业务查询需要的字段设计到rowkey里面,这样在查询的时候对rowkey加上一定范围的限制。
Scan scan = new Scan(); scan.setStartRow("001".getBytes()); scan.setStopRow("1000".getBytes()); scan.setCaching(10000);//hbase扫描时的缓存 scan.setBatch(100);//一次扫描数据
2.Filter
除了对rowkey的scan外,HBase为筛选数据提供了一组过滤器,通过这个过滤器可以在HBase中的数据的多个维度(行,列,数据版本)上进行对数据的筛选操作,也就是说过滤器最终能够筛选的数据能够细化到具体的一个存储单元格上(由行键,列明,时间戳定位)。
filter并不能做到像rowkey那样快速定位到数据,他的作用仅仅是过滤,在scan的过程中对列族的某个字段进行一定条件的判断。
通常来讲,scan来定位查找的大概范围,fitler来过滤找到具体的值。
下面看看hbase里面都提供了哪些filter
2.1. RowFilter
筛选出匹配的所有的行,对于这个过滤器的应用场景,是非常直观的:使用BinaryComparator可以筛选出具有某个行键的行,或者通过改变比较运算符(下面的例子中是CompareFilter.CompareOp.EQUAL)来筛选出符合某一条件的多条数据,以下就是筛选出行键为row1的一行数据:
Filter rf = new RowFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("row1"))); // OK 筛选出匹配的所有的行
2.2. PrefixFilter
筛选出具有特定前缀的行键的数据。这个过滤器所实现的功能其实也可以由RowFilter结合RegexComparator来实现,不过这里提供了一种简便的使用方法,以下过滤器就是筛选出行键以row为前缀的所有的行:
Filter pf = new PrefixFilter(Bytes.toBytes("row")); // OK 筛选匹配行键的前缀成功的行
2.3. KeyOnlyFilter
这个过滤器唯一的功能就是只返回每行的行键,值全部为空,这对于只关注于行键的应用场景来说非常合适,这样忽略掉其值就可以减少传递到客户端的数据量,能起到一定的优化作用:
Filter kof = new KeyOnlyFilter(); // OK 返回所有的行,但值全是空
2.4. RandomRowFilter
从名字上就可以看出其大概的用法,本过滤器的作用就是按照一定的几率(<=0会过滤掉所有的行,>=1会包含所有的行)来返回随机的结果集,对于同样的数据集,多次使用同一个RandomRowFilter会返回不通的结果集,对于需要随机抽取一部分数据的应用场景,可以使用此过滤器:
Filter rrf = new RandomRowFilter((float) 0.8); // OK 随机选出一部分的行
2.5. InclusiveStopFilter
扫描的时候,我们可以设置一个开始行键和一个终止行键,默认情况下,这个行键的返回是前闭后开区间,即包含起始行,但不包含终止行,如果我们想要同时包含起始行和终止行,那么我们可以使用此过滤器:
Filter isf = new InclusiveStopFilter(Bytes.toBytes("row1")); // OK 包含了扫描的上限在结果之内
2.6. FirstKeyOnlyFilter
如果你只想返回的结果集中只包含第一列的数据,那么这个过滤器能够满足你的要求。它在找到每行的第一列之后会停止扫描,从而使扫描的性能也得到了一定的提升:
Filter fkof = new FirstKeyOnlyFilter(); // OK 筛选出第一个每个第一个单元格
2.7. ColumnPrefixFilter
顾名思义,它是按照列名的前缀来筛选单元格的,如果我们想要对返回的列的前缀加以限制的话,可以使用这个过滤器:
Filter cpf = new ColumnPrefixFilter(Bytes.toBytes("qual1")); // OK 筛选出前缀匹配的列
2.8. ValueFilter
按照具体的值来筛选单元格的过滤器,这会把一行中值不能满足的单元格过滤掉,如下面的构造器,对于每一行的一个列,如果其对应的值不包含ROW2_QUAL1,那么这个列就不会返回给客户端:
Filter vf = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("ROW2_QUAL1")); // OK 筛选某个(值的条件满足的)特定的单元格
2.9. ColumnCountGetFilter
这个过滤器来返回每行最多返回多少列,并在遇到一行的列数超过我们所设置的限制值的时候,结束扫描操作:
Filter ccf = new ColumnCountGetFilter(2); // OK 如果突然发现一行中的列数超过设定的最大值时,整个扫描操作会停止
2.10. SingleColumnValueFilter
用一列的值决定这一行的数据是否被过滤。在它的具体对象上,可以调用setFilterIfMissing(true)或者setFilterIfMissing(false),默认的值是false,其作用是,对于咱们要使用作为条件的列,如果这一列本身就不存在,那么如果为true,这样的行将会被过滤掉,如果为false,这样的行会包含在结果集中。
SingleColumnValueFilter scvf = new SingleColumnValueFilter( Bytes.toBytes("colfam1"), Bytes.toBytes("qual2"), CompareFilter.CompareOp.NOT_EQUAL, new SubstringComparator("BOGUS")); scvf.setFilterIfMissing(false); scvf.setLatestVersionOnly(true); // OK
2.11. SingleColumnValueExcludeFilter
这个与10种的过滤器唯一的区别就是,作为筛选条件的列的不会包含在返回的结果中。
2.12. SkipFilter
这是一种附加过滤器,其与ValueFilter结合使用,如果发现一行中的某一列不符合条件,那么整行就会被过滤掉:
Filter skf = new SkipFilter(vf); // OK 发现某一行中的一列需要过滤时,整个行就会被过滤掉
2.13. WhileMatchFilter
这个过滤器的应用场景也很简单,如果你想要在遇到某种条件数据之前的数据时,就可以使用这个过滤器;当遇到不符合设定条件的数据的时候,整个扫描也就结束了:
Filter wmf = new WhileMatchFilter(rf); // OK 类似于Python itertools中的takewhile
2.14. FilterList
用于综合使用多个过滤器。其有两种关系:FilterList.Operator.MUST_PASS_ONE和FilterList.Operator.MUST_PASS_ALL,默认的是FilterList.Operator.MUST_PASS_ALL,顾名思义,它们分别是AND和OR的关系,并且FilterList可以嵌套使用FilterList,使我们能够表达更多的需求:
List filters = new ArrayList(); filters.add(rf); filters.add(vf); FilterList fl = new FilterList(FilterList.Operator.MUST_PASS_ALL, filters); // OK 综合使用多个过滤器, AND 和 OR 两种关系