手记

HBase Java API 批量操作

之前我们是这样获取数据的:

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分钟左右。

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

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函数批量获取数据

查看HBase的API,我们可以发现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之内,

使用上述代码查询下表:

image.png

输出结果:

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)就会返回该列的值。

删除单行数据

删除一行数据很简单,我们来看个示例:

Table table = conn.getTable(tableName); //获取表   byte[] row = Bytes.toBytes("row1");//定义行Delete delete = new Delete(row);//创建delete对象table.delete(delete);//删除

这段代码就可以删除行键为row1的行。

删除多行数据

如何删除多行数据呢?

相信你已经猜到了,既然get()方法有重载方法,那应该delete()方法也有,确实:

Table table = conn.getTable(tableName);
List<Delete> deletes = new ArrayList<>();for(int i = 1 ; i < 5;i++){
    byte[] row = Bytes.toBytes("row" + i);
    Delete delete = new Delete(row);
    deletes.add(delete);
}
table.delete(deletes);

这样就可以删除多行数据啦。

每一次只添加一个数据显然不像是大数据开发,在开发项目的时候也肯定会涉及到大量的数据操作。

使用Java进行批量数据操作,其实就是循环的在Put对象中添加数据最后在通过Table对象提交。

如何进行批量操作呢,讲到批量操作,相信大家肯定第一时间会想到循环?

没错,使用循环确实就可以添加多个数据了,示例:

Table tableStep3 = connection.getTable(tableStep3Name);// 循环添加数据byte[] row = Bytes.toBytes("20001");
Put put = new Put(row);for (int i = 1; i <= 4; i++) {    byte[] columnFamily = Bytes.toBytes("data");    byte[] qualifier = Bytes.toBytes(String.valueOf(i));    byte[] value = Bytes.toBytes("value" + i);
    put.addColumn(columnFamily, qualifier, value);
}

tableStep3.put(put);

代码执行结果:

image.png

可以发现,这一段代码向同一个行中添加了四列数据。

我们要添加多行数据应该如何处理呢,我猜你肯定想到了:使用集合!

List<Put> puts = new ArrayList<>();// 循环添加数据for (int i = 1; i <= 4; i++) {    byte[] row = Bytes.toBytes("row" + i);
    Put put = new Put(row);    byte[] columnFamily = Bytes.toBytes("data");    byte[] qualifier = Bytes.toBytes(String.valueOf(i));    byte[] value = Bytes.toBytes("value" + i);
    put.addColumn(columnFamily, qualifier, value);
    puts.add(put);
}
Table table = connection.getTable(tableName);
table.put(puts);

上述代码向HBase中添加了四行数据,结合上次实训,可以发现table对象的put()方法是一个重载方法既可以接收Put对象也可以接收Put集合

添加完数据的表结构:

image.png



作者:MasterXiao
链接:https://www.jianshu.com/p/dc0e88fdce8e


0人推荐
随时随地看视频
慕课网APP