在从HBase表中获取多个记录的实现过程中,我们遇到了有关获取记录的最佳方法的讨论。
第一个实现是这样的:
FilterList filterList = new FilterList(Operator.MUST_PASS_ONE);
for (String rowKey : rowKeys) {
filterList.addFilter(new RowFilter(CompareOp.EQUAL,new BinaryComparator(Bytes.toBytes(rowKey))));
}
Scan scan = new Scan();
scan.setFilter(filterList);
ResultScanner resultScanner = table.getScanner(scan);
第二种实现是这样的:
List<Get> listGet = rowKeys.stream()
.map(entry -> {
Get get = new Get(Bytes.toBytes(entry));
return get;
})
.collect(Collectors.toList());
Result[] results = table.get(listGet)
我直接看到的唯一区别是filterList将执行全表扫描,而multiget则不会执行任何操作。
但是,一个相对于另一个有什么其他好处?另外,当HBase发现filterList中的所有过滤器都是RowFilters时,它会执行某种优化并执行multiget而不是进行全表扫描吗?
最佳答案
TLDR:它取决于行数(已读取和想要的),过滤器的数量以及所搜索数据的紧密程度。
但是,一个相对于另一个有什么其他好处?
通常,它有不同的用途。如果要读取绝大多数数据而忽略其中的一些数据,请使用带过滤器的扫描。如果您只想在一个大表中占用几行,请使用Multiget。
在寻找答案时,我发现了有关Hbase multiget vs scan with RowFilter的讨论。
这些是要点:
扫描将始终扫描所有行(或指定的开始行和停止行之间的所有行)。过滤器可以过滤掉行,但是无论如何都将读取它们。
MultiGet对每个Get进行搜索(在某种意义上)。
如果MultiGet中Gets的数量与总行数相比非常少,则最好使用MultiGet。但是,如果您能够在“扫描”操作中指定开始和停止行,则扫描会更快(因为您限制了将要读取的行数):
new Scan().withStartRow(startRow).withStopRow(stopRow)
另外,当HBase发现filterList中的所有过滤器都是RowFilters时,它会执行某种优化并执行multiget而不是进行全表扫描吗?
不,我认为它没有任何优化。我认为,太多的过滤器甚至会减慢扫描速度,因为它必须通过每一行的所有过滤器。参见FilterList documentation:
FilterList.Operator.MUST_PASS_ONE的计算是非延迟的:始终对所有过滤器进行评估。