高效查询hbase

zaqlnxep  于 2021-06-02  发布在  Hadoop
关注(0)|答案(2)|浏览(450)

我使用java作为查询hbase的客户机。
我的hbase表设置如下:

ROWKEY     |     HOST     |     EVENT
-----------|--------------|----------
21_1465435 | host.hst.com |  clicked
22_1463456 | hlo.wrld.com |  dragged
    .             .             .
    .             .             .
    .             .             .

我要做的第一件事就是列出所有 ROWKEYs 有哪些 host.hst.com 与之相关。
我可以在列上创建一个扫描仪 host 对于每行值 column value = host.hst.com 我将添加相应的 ROWKEY 加入名单。似乎很有效率。 O(n) 用于获取所有行。
现在是最困难的部分。对于每个 ROWKEY 在列表中,我需要得到相应的 EVENT .
如果我用普通的 GET 获取单元格的命令 (ROWKEY, EVENT) ,我相信扫描仪是在 EVENT 这需要 O(n) 找到正确单元格并返回值的时间。这对每个人来说都是相当糟糕的时间复杂性 ROWKEY . 把两者结合起来 O(n^2) .
有没有更有效的方法?
非常感谢您的帮助!

6ljaweal

6ljaweal1#

首先,您的rowkey设计应该是完美的,在此基础上您可以定义用于查询的访问模式。
1) 如果您知道可以预先访问哪些行键,那么get是很好的
在这种情况下,您可以使用如下方法,它将返回结果数组。

/**
     * Method getDetailRecords.
     * 
     * @param listOfRowKeys List<String>
     * @return Result[]
     * @throws IOException
     */
    private Result[] getDetailRecords(final List<String> listOfRowKeys) throws IOException {
        final HTableInterface table = HBaseConnection.getHTable(TBL_DETAIL);
        final List<Get> listOFGets = new ArrayList<Get>();
        Result[] results = null;
        try {
            for (final String rowkey : listOfRowKeys) {// prepare batch of get with row keys
   // System.err.println("get 'yourtablename', '" + saltIndexPrefix + rowkey + "'");
                final Get get = new Get(Bytes.toBytes(saltedRowKey(rowkey)));
                get.addColumn(COLUMN_FAMILY, Bytes.toBytes(yourcolumnname));
                listOFGets.add(get);
            }
            results = table.get(listOFGets);

        } finally {
            table.close();
        }
        return results;
    }

根据我的经验,如果我们没有完美的rowkey设计,hbase扫描性能会有点低。我建议您是否选择扫描上述场景。
fuzzyrowfilter(请参阅hbase的最终版本)这在我们的案例中非常有用,我们使用了诸如map reduce之类的批量客户端以及独立的hbase客户端
此过滤器作用于行键,但方式模糊。它需要一个应该返回的行键列表,以及一个伴随的byte[]数组,该数组表示行键中每个字节的重要性。建造师是这样的:

FuzzyRowFilter(List<Pair<byte[], byte[]>> fuzzyKeysData)

fuzzykeysdata通过采用以下两个值中的一个值来指定所提到的行键字节的重要性:
0表示行键中相同位置的字节必须按原样匹配。1表示相应的行键字节无关紧要,并且始终被接受。
示例:部分行键匹配一个可能的示例是匹配部分键,但不是从左到右,而是在复合键的某个位置。假设行键格式为,具有固定长度的部分,其中为4、2、4和2字节长。应用程序现在请求在任何一年的1月份执行某些操作(编码为99)的所有用户。则行键和模糊数据的对将如下所示:
行键“????99????\U 01”,其中“?”是任意字符,因为它被忽略。fuzzy data=“\x01\x01\x01\x00\x00\x00\x00\x01\x01\x01\x01\x00\x00\x00”换句话说,fuzzy data数组指示过滤器查找所有与“????99???U 01”匹配的行键,其中“?”将接受任何字符。
这个过滤器的一个优点是,当它到达一个匹配行的末尾时,它可能会计算出下一个匹配行的键。它实现getnextcellhint()方法来帮助服务器快速转发到下一个可能匹配的行范围。这加快了扫描速度,特别是当跳过的范围相当大时。示例4-12使用过滤器从测试数据集中获取特定行。
按列前缀筛选的示例

List<Pair<byte[], byte[]>> keys = new ArrayList<Pair<byte[], byte[]>>();
keys.add(new Pair<byte[], byte[]>(
  Bytes.toBytes("row-?5"), new byte[] { 0, 0, 0, 0, 1, 0 }));
Filter filter = new FuzzyRowFilter(keys);

Scan scan = new Scan()
  .addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5"))
  .setFilter(filter);
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
  System.out.println(result);
}
scanner.close();

示例代码还向扫描中添加了一个过滤列,以保持输出简短:
正在向表中添加行。。。扫描结果:

keyvalues={row-05/colfam1:col-01/1/Put/vlen=9/seqid=0,
           row-05/colfam1:col-02/2/Put/vlen=9/seqid=0,
           ...
           row-05/colfam1:col-09/9/Put/vlen=9/seqid=0,
           row-05/colfam1:col-10/10/Put/vlen=9/seqid=0}
keyvalues={row-15/colfam1:col-01/1/Put/vlen=9/seqid=0,
           row-15/colfam1:col-02/2/Put/vlen=9/seqid=0,
           ...
           row-15/colfam1:col-09/9/Put/vlen=9/seqid=0,
           row-15/colfam1:col-10/10/Put/vlen=9/seqid=0}

测试代码连接将向表中添加20行,命名为row-01到row-20。我们要检索与模式行-?5匹配的所有行,换句话说,检索以数字5结尾的所有行。以上输出证实了正确的结果。

0mkxixxg

0mkxixxg2#

你的工作是什么 n 在这里??手拿着rowkey-我想你是说hbase rowkey-不是手工制作的??-这对hbase来说很快/容易。把它看作o(1)。
如果rowkey是您创建的实际列。。那就是你的问题。改用hbase提供的rowkey。
所以让我们继续—假设您(a)已经正确地使用了提供的hbase rowkey -或者已经把你的结构修好了。
在这种情况下,您可以简单地创建一个单独的 get 对于每个 (rowkey, EVENT) 数值如下:

Perform a `get` with the given `rowkey`. 
In your result then filter out EVENT in <yourEventValues for that rowkey>

因此,您将获取给定rowkey的所有最近(最新时间戳)条目。这大概比“n”小吧??然后过滤是对一列的快速操作。
您还可以通过成批执行 multiget . 节省的成本来自减少到hbase主服务器的往返次数以及主服务器/区域服务器生成的parsings/计划。
感谢op的更新:我更清楚地了解情况。我建议只使用“host |”作为rowkey。然后您可以执行范围扫描并从单个get/scan获取条目。
另一个更新
hbase支持基于rowkey前缀的范围扫描。所以你有foobarrow1,foobarrow2。。等等,然后您可以对(foobarrow,foobarrowz)进行范围扫描,它将找到所有以 foobarRow -后面有任何字母数字字符。
看看这个hbase(简单):如何在hbase shell中执行范围前缀扫描
下面是一些示例代码:

SingleColumnValueFilter filter = new SingleColumnValueFilter(
   Bytes.toBytes("columnfamily"),
   Bytes.toBytes("storenumber"),
   CompareFilter.CompareOp.NOT_EQUAL,
   Bytes.toBytes(15)
);
filter.setFilterIfMissing(true);
Scan scan = new Scan(
   Bytes.toBytes("20110103-1"),
   Bytes.toBytes("20110105-1")
);
scan.setFilter(filter);

请注意 20110103-1 以及 20110105-1 提供一系列要搜索的行键。

相关问题