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

一、介绍

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 exception
			e.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 exception
			e.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也具有形似的属性,可以通过修改这些属性去对数据获取进行调优,从而使得提高数据获取的效率。


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值