HBase多范围扫描

10

我有一个HBase表格,需要获取多个范围内的结果。例如,我可能需要从不同的范围(如行1-6、100-150)中获取数据。我知道每次扫描都可以定义起始行和停止行。但是如果我有6个范围,我需要进行6次扫描。是否有一种方法可以通过一次扫描或一个RPC从多个范围中获取结果?我的HBase版本是0.98。


2
Hbase 2有MultiRowRanger,允许设置多个范围。如果范围很小,则多个Scans查询也会更快。 - Rahul Sharma
多行游侠是否只会为多个范围发送一个RPC? - Cheng Chen
如果您无法使用MultiRowRangeFilter,则多次扫描是最佳选择,特别是当范围之间的键数很大时。 - kostya
我更改了我的HBase 2并最终使用了MultiRowRangeFilter。 - Cheng Chen
Rahul和kostya,你们俩能否在回答中发布MultiRowRangeFilter?我已经采纳了你们的建议来解决我的问题。顺便说一句,如果你们不介意的话,能否给我的问题点个赞?我需要一些声望才能有评论别人问题的特权。 - Cheng Chen
很好的问题!因为没有人回答,所以我想给出一个详细的例子来回答。请仔细阅读。 - Ram Ghadiyaram
1个回答

5

支持扫描多个行键范围的过滤器。它可以从传递的列表构造行键范围,每个区域服务器都可以访问该列表。

当仅扫描一个小的行键范围时,HBase非常高效。如果用户需要在一个扫描中指定多个行键范围,则典型的解决方案有:

  1. 通过FilterList来实现一组行键过滤器;
  2. 使用在HBase上的SQL层与两个表进行连接,例如hive、phoenix等。不过,这两种解决方案都效率低下。
  3. 它们都不能利用范围信息执行扫描期间的快速转发,这是非常耗时的。如果范围的数量相当大(例如数百万),连接是一个合适的解决方案,尽管它很慢。
    然而,有些情况下用户只想指定少量的范围进行扫描(例如<1000个范围)。在这种情况下,这两种解决方案都无法提供令人满意的性能。

MultiRowRangeFilter支持这种用例(扫描多个行键范围),它可以从用户指定的列表构造行键范围,并在扫描期间执行快速转发。因此,扫描将非常高效。

package chengchen;

import java.util.ArrayList;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.MultiRowRangeFilter;
import org.apache.hadoop.hbase.filter.MultiRowRangeFilter.RowKeyRange;
import org.apache.hadoop.hbase.util.Bytes;



public class MultiRowRangeFilterTest {
    public static void main(String[] args) throws Exception {
        if (args.length < 1) {
            throw new Exception("Table name not specified.");
        }
        Configuration conf = HBaseConfiguration.create();
        HTable table = new HTable(conf, args[0]);

        TimeCounter executeTimer = new TimeCounter();
        executeTimer.begin();
        executeTimer.enter();
        Scan scan = new Scan();
        List<RowKeyRange> ranges = new ArrayList<RowKeyRange>();
        ranges.add(new RowKeyRange(Bytes.toBytes("001"), Bytes.toBytes("002")));
        ranges.add(new RowKeyRange(Bytes.toBytes("003"), Bytes.toBytes("004")));
        ranges.add(new RowKeyRange(Bytes.toBytes("005"), Bytes.toBytes("006")));
        Filter filter = new MultiRowRangeFilter(ranges);
        scan.setFilter(filter);
        int count = 0;
        ResultScanner scanner = table.getScanner(scan);
        Result r = scanner.next();
        while (r != null) {
            count++;
            r = scanner.next();
        }
        System.out
                .println("++ Scanning finished with count : " + count + " ++");
        scanner.close();


    }

}

请查看这个测试案例,以了解如何在Java中实现。

注意:然而,在我看来,这种需求最好使用SOLR或ES...您可以查看我的Solr答案以获取高层架构概述。我建议这样做是因为HBase扫描大量数据会非常慢。


嗨Ram,你的最后一句话是什么意思?能否请你澄清一下,因为它不太清楚。你是说Solr或ES会是这个问题的更好解决方案吗?如果是这样,能否请你添加一个高层次的架构视图来说明它将如何工作? - eboni
根据我的经验,Solr和Hbase一起使用非常好,可以用于从Hbase查询数据,并且还可以发布到UI仪表板中。由于这个问题与Solr无关,所以我决定不加入它。 - Ram Ghadiyaram
@eboni:我更新了我的回答...由于solr是不同的上下文,我无法在这里详细说明。我在上面的回答中添加了链接。 - Ram Ghadiyaram

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接