之前我们是这样获取数据的:
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; }
根据这种批量的方法,10000
个row
进行查询,时间稳定在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
是单个结果,这里存放的是一行的所有数据,result
的rowCells()
方法会返回这一行所有的列(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
共同学习,写下你的评论
评论加载中...
作者其他优质文章