我有一个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结果的正确方式。
是否有一种更高效的方法来完成它,或者有一些自动的功能?
我怀疑代码中的关键性能瓶颈是您在执行scanner.next()时没有指定要返回多少行。通过这种方式,您将为每一行执行到集群的往返。最好指出您希望一次返回多少行,以便将它们全部打包到一个RPC调用中。这里的正确参数取决于您的行实际有多大(即列内容)和服务器上的内存。尝试一下这个设置,但是对于小的行,我通常使用数千或数万。通过这种方式,您应该可以看到显著的加速。
为清晰起见,使用示例编辑:
这将在一个RPC中将一行的所有列返回给服务器:
Result result = scanner.next()
这将返回20行,其中每行都有相关的列,全部在一个RPC中返回到服务器:
Result result = scanner.next(20)
如果满足扫描的实际存在的行数少于20行,则扫描将返回任何可用的行数。
所以做一个两级循环:外水平检查结果是null或比你要求的小(即没有更多的结果),而实际上内循环遍历所有行返回每个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;
}
这样的东西应该比你现在所拥有的要快得多,特别是如果你的扫描必须返回数千行。
首先有一个bug: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<String[]>
(如果您知道单元格的数量,或其他),Object[],或您自己的RowSection类,具有int, String和其他字段。
当cloneValue
似乎返回一个byte[]
时,简单地使用它。
List<byte[]> rowSection = new ArrayList<>();
byte[] value = CellUtil.cloneValue(cell);
rowSection.add(value);
还有很多需要改进的地方。