HBase Java API 开发:批量操作 第1关:批量获取数据

30 篇文章 5 订阅
15 篇文章 11 订阅

在上次实训中我们是这样获取数据的:

Get get = new Get(Bytes.toBytes("row1"));//定义get对象
Result result = table.get(get);//通过table对象获取数据

那么问题来了,我们想要获取多条数据,比如说查询1万条数据怎么办呢?

可能我们第一时间就会想到循环,例如:

String tableName = "test";
Table table = connection.getTable( TableName.valueOf(tableName));// 获取表
for (String rowkey : rowkeyList){
Get get = new Get(Bytes.toBytes(rowkey));
Result result = table.get(get);
for (Cell kv : result.rawCells()) {
String value = Bytes.toString(CellUtil.cloneValue(kv));
list.add(value);
}
}

这样做是非常低效的,如果有10000条数据那我们需要发送10000次请求,这样非常耗时,如果在自己本机上尝试,查询时间可能在5分钟左右。

这样肯定不行,我们在HBaseTable对象和子类的源码中找找看有没有解决办法,忽然眼前一亮:

public Result[] get(List<Get> gets) throws IOException {
if (gets.size() == 1) {
return new Result[]{get(gets.get(0))};
}
try {
Object[] r1 = new Object[gets.size()];
batch((List<? extends Row>)gets, r1, readRpcTimeoutMs);
// Translate.
Result [] results = new Result[r1.length];
int i = 0;
for (Object obj: r1) {
// Batch ensures if there is a failure we get an exception instead
results[i++] = (Result)obj;
}
return results;
} catch (InterruptedException e) {
throw (InterruptedIOException)new InterruptedIOException().initCause(e);
}
}

使用get函数批量获取数据

查看HBaseAPI,我们可以发现Table对象的get()函数不仅可以接收Get对象,也同样可以接收Get集合,现在我们试试get(List<Get> gets)函数的效果如何。

public List<String> getData(Table table, List<String> rows) throws Exception {
List<Get> gets = new ArrayList<>();
for (String str : rows) {
Get get = new Get(Bytes.toBytes(str));
gets.add(get);
}
List<String> values = new ArrayList<>();
Result[] results = table.get(gets);
for (Result result : results) {
System.out.println("Row:" + Bytes.toString(result.getRow()));
for (Cell kv : result.rawCells()) {
String family = Bytes.toString(CellUtil.cloneFamily(kv));
String qualifire = Bytes.toString(CellUtil.cloneQualifier(kv));
String value = Bytes.toString(CellUtil.cloneValue(kv));
values.add(value);
System.out.println(family + ":" + qualifire + "\t" + value);
}
}
return values;
}

根据这种批量的方法,10000row进行查询,时间稳定在4s之内,

使用上述代码查询下表:

输出结果:

Row:20001 data:1 value1 data:2 value2 data:3 value3 data:4 value4 Row:20002 data:1 name1 data:2 name2 data:3 name3 data:4 name4

代码解释:

  • table.get(gets)会返回一个Result[]结果数组,里面存放了本次查询的所有数据,我们可以通过这个数组来遍历我们需要的数据;
  • result.rawCells()result是单个结果,这里存放的是一行的所有数据,resultrowCells()方法会返回这一行所有的列(Cell)的集合;
  • Cell对象是单个的列,要获取列中的值可以通过CellUtil.cloneXXX()方法,如cloneValue(cell)就会返回该列的值。

编程要求

好了,到你啦,使用本关知识,在右侧编辑器begin-end处补充代码,现有表step1_student如下:

需要你编写程序获取表中行键为20182020的数据并输出。

package step1;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Get;
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.client.Table;
import org.apache.hadoop.hbase.client.TableDescriptor;
import org.apache.hadoop.hbase.generated.rest.rest_jsp;
import org.apache.hadoop.hbase.util.Bytes;
public class Task {
 public void batchGet() throws Exception {
   /********* Begin *********/
 Configuration config = HBaseConfiguration.create();
   Connection Connection = ConnectionFactory.createConnection(config);
   List<String> rows = new ArrayList<>();
   rows.add("2018");
   //rows.add("2019");
   rows.add("2020");
   TableName tableName = TableName.valueOf(Bytes.toBytes("step1_student"));
   Table table = Connection.getTable(tableName);
   getData(table,rows);
   /********* End *********/
 }
public List<String> getData(Table table, List<String> rows) throws Exception {
 List<Get> gets = new ArrayList<>();
 for (String str : rows) {
 Get get = new Get(Bytes.toBytes(str));
 gets.add(get);
 }
 List<String> values = new ArrayList<>();
 Result[] results = table.get(gets);
 for (Result result : results) {
 System.out.println("Row:" + Bytes.toString(result.getRow()));
 for (Cell kv : result.rawCells()) {
 String family = Bytes.toString(CellUtil.cloneFamily(kv));
 String qualifire = Bytes.toString(CellUtil.cloneQualifier(kv));
 String value = Bytes.toString(CellUtil.cloneValue(kv));
 values.add(value);
 System.out.println(family + ":" + qualifire + "\t" + value);
 }
 }
 return values;
}
}

start-dfs.sh
start-hbase.sh

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值