【问题标题】:How to convert HBase rows to an array of objects如何将 HBase 行转换为对象数组
【发布时间】:2021-11-20 15:31:27
【问题描述】:

我有一个 rest API,它使用 java 客户端从 HBase 检索大量行。

我已经实现了以下代码来将 hbase 行转换为数组数组。

List<List<String>> finalList = new ArrayList<List<String>>();
        ResultScanner scanner = table.getScanner(scan);
        List<String> rowSection = new ArrayList<String>();
        try {
            for (Result result = scanner.next(); (result != null); result = scanner.next()) {
                rowSection.clear();
                for (Cell cell : result.listCells()) {
                    String value = Bytes.toString(CellUtil.cloneValue(cell));
                    rowSection.add(value);
                }
                finalList.add(rowSection);
            }
            System.out.println("ARRAY SIZE: " + finalList.size());
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }

我可以轻松地将其转换为对象数组,但我不确定这是否是转换 hbase 结果的正确方法。

有没有更高效的方式来做这件事,还是有一些自动的功能?

【问题讨论】:

    标签: java arrays object hbase cloudera


    【解决方案1】:

    我怀疑您代码中的关键性能瓶颈是您在执行scanner.next() 时未指定要返回的行数。这样,您将对每一行的集群进行往返。最好指示一次要返回多少行,这样它们就会全部打包到一个 RPC 调用中。此处正确的参数取决于您的行实际有多大(即列内容)和您在服务器上的内存。玩弄这个设置,但我通常使用数千或数万的小行。通过这种方式,您应该会看到显着的加速。

    为了清楚起见,用一个例子编辑:

    这将在一个 RPC 中向服务器返回 1 行以及该行的所有列:

    Result result = scanner.next()
    

    这将返回 20 行,其中每一行的所有相关列,都在单个 RPC 中发送到服务器:

    Result result = scanner.next(20)
    

    如果满足您的扫描的实际存在少于 20 行,则扫描将返回任何可用的。

    所以尝试做一个两级循环:外部级别检查结果是否为空或小于您要求的结果(即没有更多可用结果),而内部循环实际上循环遍历每个 RPC 返回的所有行。我没有测试过这个,但是像这样:

       int HOW_MANY_ROWS = 20
        Result result[];
        do
                    {
                        result = m_scanner.next(HOW_MANY_ROWS);
                        for(Result row : result)
                        {
                            byte rowKey[] = row.getRow());
                            // rest of your code for this row goes here
                        }   
                        if(scanRes.result < HOW_MANY_ROWS)
                        break;
                    }
    

    这样的事情应该比现在快很多,尤其是当您的扫描必须返回数千行时。

    【讨论】:

    • 你能更好地解释一下我应该使用哪些设置吗?
    • 我用一个程式化的例子编辑了答案。希望对您有所帮助。
    • 我会测试它并告诉你,谢谢!
    【解决方案2】:

    首先有一个错误:finalList 多次填充单个对象,最后多次包含最后一条记录。应该这样做:

    List<List<String>> finalList = new ArrayList<>();
    ResultScanner scanner = table.getScanner(scan);
    try {
        for (Result result = scanner.next(); (result != null); result = scanner.next()) {
            List<String> rowSection = new ArrayList<>();
    

    然后是保留一排。它可以是List&lt;String[]&gt;(如果你知道单元格的数量,或者其他什么,Object[],或者你自己的 RowSection 类,带有 int、String 和其他字段。

    cloneValue 似乎返回了 byte[],只需使用它即可。

    List<byte[]> rowSection = new ArrayList<>();
    
                    byte[] value = CellUtil.cloneValue(cell);
                    rowSection.add(value);
    

    还有更多需要改进的地方。

    【讨论】:

      猜你喜欢
      • 2018-02-13
      • 2022-01-23
      • 2011-01-29
      • 2018-07-27
      • 2018-12-12
      • 1970-01-01
      相关资源
      最近更新 更多