HBase总结(4)--数据扫描与Scan对象

来源:互联网 发布:生物竞赛题库软件 编辑:程序博客网 时间:2024/06/05 05:45

一、介绍

Put、Delete与Get对象都是Row的子类,从该继承关系中我们就可以了解到Get、Delete与Pu对象本身就只能进行单行的操作,HBase客户端还提供了一套能够进行全表扫描的API,方便用户能够快速对整张表进行扫描,以获取想要的结果---scan

二、流程介绍

全表扫描是一种不需要行键值的操作,因此初始化时不需要指定行键值,因此就产生了不同的使用方法

1、不进行Scan对象创建的全表扫描

在该过程中,Htable对象会在扫描请求发送前隐式的创建一个scan对象,然后传递给Hbase服务器集群。

public void scanWithoutInit(String tableName,String family){Configuration conf=init();try {HBaseAdmin admin=new HBaseAdmin(conf);if(!admin.tableExists(tableName)){System.err.println("the table "+tableName+" is not exist");admin.close();System.exit(1);}//创建表连接HTable table=new HTable(conf, tableName);//获取全表扫描ResultScanner resultScanner=table.getScanner(Bytes.toBytes(family));//对结果进行显示Iterator<Result> results=resultScanner.iterator();while(results.hasNext()){Result result=results.next();for(KeyValue kv:result.raw()){System.out.println(Bytes.toString(kv.getRow()));System.out.println(Bytes.toString(kv.getFamily()));System.out.println(Bytes.toString(kv.getQualifier()));System.out.println(Bytes.toString(kv.getValue()));}}} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}

getScanner()方法时,如果不输入指定的scan对象,则需要输入相应的列簇或者列。因此在不进行scan对象创建的扫描中,需要明确指出列簇或者列,如果需要扫描多个列簇时,该方法就无法起到作用了。

2、进行初始化的全表扫描

初始化一个scan对象,然后对该对象进行相应的配置过,通过 getScanner(Scan scan) 函数进行全表扫描。

public void scanWithInit(String tableName){Configuration conf=init();try {HBaseAdmin admin=new HBaseAdmin(conf);if(!admin.tableExists(tableName)){System.err.println("the table "+tableName+" is not exist");admin.close();System.exit(1);}//创建扫描类Scan scan=new Scan();scan.setStartRow(Bytes.toBytes("row-1"));scan.setStopRow(Bytes.toBytes("row-9"));//创建表连接HTable table=new HTable(conf, tableName);ResultScanner rs=table.getScanner(scan);Result result;while((result=rs.next())!=null){KeyValue[] kvs=result.raw();for(KeyValue kv:kvs){System.out.println(Bytes.toString(kv.getRow()));System.out.println(Bytes.toString(kv.getFamily()));System.out.println(Bytes.toString(kv.getQualifier()));System.out.println(Bytes.toString(kv.getValue()));}}rs.close();table.close();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}

在上段代码中,使用了setStartRow() 与 setStopRow() 两个函数进行调优。Scan有多个函数可以进行对全表扫描做出相应的规范。

3、数据遍历与显示ScannerResult

通过上述两种方法可以发送对一张表是遍历请求,当发送后,服务器会相应的启动全表扫面程序,从而准备向客户端返回相应的数据。因此根据客户端的遍历需要对数据尽心请求,然后将请求的结果进行返回,客户端拿到后进行展示

(1)next()的单行返回数据的方法

ResultScanner rs=table.getScanner(Bytes.toBytes(family));//进项单行获取演示Result result=null;while((result=rs.next())!=null){KeyValue[] kvs=result.raw();for(KeyValue kv:kvs){System.out.println(Bytes.toString(kv.getRow()));System.out.println(Bytes.toString(kv.getFamily()));System.out.println(Bytes.toString(kv.getQualifier()));System.out.println(Bytes.toString(kv.getValue()));}}rs.close();

next()方法会默认想客户端请求发送一行数据请求,刚服务器端的scan程序接收到请求后会将经需要返回的数据封装成一个result对象返回给客户端,因此客户端可以通过result对象去接受该行数据。接收到的数据则跟Get中的result使用方法是相同的。

(2)next(int n)的多行返回数据的方法

next(int n):该函数会向服务器发送多个请求,以返回多条数据请求。

//一次获取多个结果(行数据)进行展示rs=table.getScanner(Bytes.toBytes(family));Result[] results=null;while((results=rs.next(2))!=null){for(Result r:results){KeyValue[] kvs=r.raw();for(KeyValue kv:kvs){System.out.println(Bytes.toString(kv.getRow()));System.out.println(Bytes.toString(kv.getFamily()));System.out.println(Bytes.toString(kv.getQualifier()));System.out.println(Bytes.toString(kv.getValue()));}}}rs.close();
next(int n)函数返回的是一个result数组。用户接受到数据后可以进行相应的操作。

(3)迭代器遍历

//进行迭代的方式进行输出rs=table.getScanner(Bytes.toBytes(family));Iterator<Result> resultIterator=rs.iterator();while(resultIterator.hasNext()){result=resultIterator.next();KeyValue[] kvs=result.raw();for(KeyValue kv:kvs){System.out.println(Bytes.toString(kv.getRow()));System.out.println(Bytes.toString(kv.getFamily()));System.out.println(Bytes.toString(kv.getQualifier()));System.out.println(Bytes.toString(kv.getValue()));}}//关闭表rs.close();
(4)注意点

因为当用户发送一个scan全表扫描后,region服务器会为全表扫描创建扫描资源,因此长时间启用全表扫描的话会占用region服务器的大量资源,所以在要求在使用完scanner扫描器后尽快释放掉资源。

rs.close() 会告知服务其扫描器租约已经结束,服务器就会释相应的全局扫描的资源。

三、Scan对象

(1)setStartRow() / setStopRow

设置扫描的开始行与结束行,通过这两个可以直接确scan在扫描的范围,通过缩小范围可以减少扫描到时间,从而提高扫描的效率

(2)addFamily() / addColumn()

通过这两个函数,可以在列或者列簇上的扫描位置。HBase是面向lie出书的数据库,而同一个列簇的数据全部存放在同一个位置文件中。因此如果可以确定扫描那个一列簇时,可以减少扫描的范围,从而缩短扫描的时间。而在确定到某一个列时也会因为HBase的面向列存储使得其效率提高。

(3)setMaxVersion() / setMaxVersion(int version)

设置返回的版本数量,默认为返回最新的数据。第一个函数则会返回所有的版本数据,第二个函数可以设置返回的版本数量

(4)setTimeStamp(long max)

返回该时间戳的数据

(5)setTimeRange(long min,long max)

设定返回的时间戳的范围,只有版本值在该范围之内的数据才会被返回到客户端

(6)setFilter(Filter f)

设置过滤器,有时候扫描全表返回的数量过大时,可以通过过滤器将不符合的数据进行过滤,这样可以减少从服务器到客户端的数据传送,挺高扫描效率。

(7)setCacheBlocks(boole open)

在进行全表扫描过程中,服务器端提供了一个缓存区,该缓存区可以将指定的数据量全部放入到内存中,这样可以提高读取效率。缓存区的打开也可以通过htable客户端进行打开。在开发后用户可以通过 setCache(int n)的方式设置每次缓存的数量为多少。通过调整该函数以提高读取的效率。

四、总结

scan的全表扫描区别于其他三个操作,虽然获取数据与Get获取的数据是相同的,其与Get也具有形似的属性,可以通过修改这些属性去对数据获取进行调优,从而使得提高数据获取的效率。


0 0
原创粉丝点击