HBase总结(2)--数据查询与Get对象

一、介绍

在HBase客户端的API中提供了两种从服务器端获取数据的方式。Get行获取和Scan扫描表的方式。下面就简单介绍一些使用Get获取数据时的使用方法

二、数据获取

Get数据的获取与上节Put数据插入一样,分为多种使用方式。

1、单行获取:get(Get get)

单行获取每次RPC请求值发送一个Get对象中的数据,因为Get对象初始化时需要输入行键,因此可以理解为一个Get对象就代表一行。一行中可以包含多个列簇或者多个列等信息

public void get(String tableName,String rowKey,String family,String qualifier)
	{
		Configuration conf=init();
		try {
			//进行管理员获取
			HBaseAdmin admin=new HBaseAdmin(conf);
			if(!admin.tableExists(Bytes.toBytes(tableName)))
			{
				System.err.println("the table "+tableName+" is not exist");
				admin.close();
				System.exit(1);
			}
			admin.close();
			//创建表连接
			HTable table=new HTable(conf,TableName.valueOf(tableName));
			//创建一个获取对象
			Get get=new Get(Bytes.toBytes(rowKey));
			//根据传入的值,进行获取判断
			if(family!=null && qualifier!=null)
			{
				get.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier));
			}
			else if(family != null && qualifier == null)
			{
				get.addFamily(Bytes.toBytes(family));
			}
			//获取数据
			Result result=table.get(get);
			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()));
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

从上述代码中我们可以看到,Get实例使用 addColumn / addFamily 着两个函数想Get中添加搜索范围。如果没有添加,则表示将整行数据进行返回。如果添加列簇,则将指定的列簇中的所有列进行返回,如果指定列,则将制定的列进行返回。

2、获取多行: get(List<Get> list)

多行获取获取实质就是在代码中对List<Get>实例进行迭代,从而发送多次数据请求(即多个RPC请求与数据操作,一次请求包含一次RPC请求和一次数据传输)。

public void getList(String tableName,String[] rows,String[] families,String[] qualifiers)
	{
		Configuration conf=init();
		try {
			//判断表是否存在
			HBaseAdmin admin=new HBaseAdmin(conf);
			if(!admin.tableExists(Bytes.toBytes(tableName)))
			{
				System.err.println("the table "+tableName+" is not exist");
				admin.close();
				System.exit(1);
			}
			//创建表连接
			HTable table=new HTable(conf, Bytes.toBytes(tableName));
			List<Get> gets=new ArrayList<>();
			int length=rows.length;
			for(int i=0;i<length;i++)
			{
				Get get=new Get(Bytes.toBytes(rows[i]));
				get.addColumn(Bytes.toBytes(families[i]), Bytes.toBytes(qualifiers[i]));
				gets.add(get);
			}
			//对结果进行递归输出
			Result[] results=table.get(gets);
			for(Result result:results)
			{
				KeyValue[] keyValues=result.raw();
				for(KeyValue kv:keyValues)
				{
					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();
		}
	}

3、获取数据或者前一行:getRowOrBefore()

该函数是HTable类提供的一个借口。作为为:当参数中的行存在时,则将本行指定的列簇进行返回,如果不存在时,则返回表中存在的指定行的前一行的数据进行返回。

public void getRowOrBefore(String tableName,String row,String family,String qualifier)
	{
		Configuration conf=init();
		try {
			HBaseAdmin admin=new HBaseAdmin(conf);
			if(!admin.tableExists(tableName))
			{
				System.out.println("the table "+tableName+" is not exist");
				admin.close();
				System.exit(1);
			}
			//创建表连接
			HTable table=new HTable(conf, tableName);
			//执行函数
			Result result=table.getRowOrBefore(Bytes.toBytes(row),Bytes.toBytes(family));
			//进行循环
			KeyValue[] keyValues=result.raw();
			for(KeyValue kv: keyValues)
			{
				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()));
				System.out.println(Bytes.toString(kv.getKey()));
			}
			table.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

注意:在函数中需要注意的是,所有行的row在HBase中的存储都是byte数组,其没有具体的类型,因此row-10 是小于 row-9。因此在进行比较是在第五位中1是小于9,HBase数据库则会认为row-10 是小于 row-9 的。如果指定顺序的话,则需要将数据的row的位数规定一致。则 row-9 应该更改为 row-09。通过这样的修改可以保证 row-09 是小于 row-10的。

4、结果显示:Result对象、KeyValue对象与Cell对象

(1)Result对象,在查询得到的结果,每一行数据会被作为一个Result对象,将数据存入到一个Result实例中。当我们需要获取一行数据时则需要获取该行数据所在的Result对象即可。该对象内部封装了一个KeyValue 对象数组。在0.98.4以前的本班。result类提供了 raw() 方法去获取整个result对象中的KeyValue数组。在0.98.4以后,则提供了一个新的节后: rowCells() 方法获取KeyValue对象,不过返回的是KeyValue 对象父类引用。

(2)KeyValue对象。该对象我们已经进行过介绍。因此这里我们只进行其使用的展示

public void KVObject(String tableName,String row,String family,String qualifier)
	{
		Configuration conf=init();
		try {
			HBaseAdmin admin=new HBaseAdmin(conf);
			if(!admin.tableExists(Bytes.toBytes(tableName)))
			{
				System.err.println("the table "+tableName+" is not exist");
				admin.close();
				System.exit(1);
			}
			admin.close();
			//创建表连接
			HTable table=new HTable(conf, tableName);
			//查询一行并返回result对象
			Get get=new Get(Bytes.toBytes(row));
			Result result=table.get(get);
			//进行循环
			KeyValue[] keyValues=result.raw();
			for(KeyValue kv: keyValues)
			{
				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()));
				System.out.println(Bytes.toString(kv.getKey()));
			}
			table.close();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

(3)Cell对象:Cell对象是KeyValue对象的父类,Cell对象中的所有方法在KeyValue对象中全部被实现。因此根据继承的特征,我们可以使用Cell对象中的API操作KeyValue对象。

public void CellObject(String tableName,String row,String family,String qualifier)
	{
		Configuration conf=init();
		try {
			//查看表是否存在
			HBaseAdmin admin=new HBaseAdmin(conf);
			if(!admin.tableExists(tableName))
			{
				System.out.println("the table "+tableName+" is not exist");
				admin.close();
				System.exit(1);
			}
			admin.close();
			//创建表连接
			HTable table=new HTable(conf, tableName);
			Get get=new Get(Bytes.toBytes(row));
			get.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier));
			Result result=table.get(get);
			Cell[] cells=result.rawCells();
			for(Cell cell:cells)
			{
				System.out.println(Bytes.toString(cell.getRow()));
				System.out.println(Bytes.toString(cell.getFamily()));
				System.out.println(Bytes.toString(cell.getQualifier()));
				System.out.println(Bytes.toString(cell.getValue()));
			}
			table.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

三、Get对象的详细配置

上述讲述了如何使用Get从HBase中获取数据,并将数据进行展示,其实Get对象中的很多属性可以控制在进行查询时的细节控制,从而控制数据从HBase服务器返回时的数据量,从而可以进行数据优化

(1)Get(byte[] row) / Get(byte[] row, RowLock lock)

初始化函数。在初始化函数时必须要指定Get将要获取的行键,第二个函数则是允许用户自己对Get上一个行锁,但是系统并不赞成用户这么使用。因为在多个客户端进行操作,且都上了自定义的行锁以后,可能会出现因为彼此的行锁需要对方的资源而死锁现象。但是两个客户端的长时间等待与系统连接资源的占用。

(2)addFamily()  / addColumn()

添加列簇 / 添加列函数。通过该函数Get在数据获取时,获取的数据范围:两个函数都不设定时获取正行的所有数据。 使用 addFamily时获取制定列簇的所有列的数据。 addColumn则获取制定列的数据

(3)setTimeStamp()

获取指定的时间戳对象

(4)setTimeRange(long minTime,long maxTime)

获取该时间戳范围内的数据

(5)setMaxVersion(int version) / setMaxVersion()

在默认情况下,Get方法之获取一列的最新的版本。但是有时需要的话则会一次获取多个版本的数据。 第一个函数可以指定确切的返回的版本数量。第二个函数则相当于setMaxVersion(Integer.MAX_VALUE)。即获取列中所有版本的 数据。

(6)setCacheBlock(boolean open)

是否打开服务器端快缓存。在HBase中,整个表以region分块的方式被分布式的存在不同的region服务器中。每一个region服务器将会维护多个region。而在每一个region中都会存在快缓存区域。当每次去读某一个KeyValue数据块时,则会将整个数据加载到缓存区中。又因为加载的数据远大于一个KeyValue所含的数据大小。所以一般情况下缓存区域内都会存放当前KeyValue对象的连续的数据。但是如果在随机读写的程序中,这种数据加载进入缓存区并没有任何的作用,反而会因为在家时间而使得数据获取时间增长。因此我们要根据实际情况去选择是否开启region上的缓存区。连续读写时,开始缓存区可以增加搜索速度。在随机读写时,关闭缓存区可以缩小读取时间。

(7)setFilter(Filter f)

添加过滤器。因为HBase并没有原声的SQL指定环境,因此在SQL语句中的where条件语句就需要通过特定的借口去实现,而Filter则就是顶替了where 语句的作用。能够实现在在数据查询中的一些精细的控制。过滤器的内容会在后面的章节进行详细的解释

四、总结

上述主要讲解了Get的使用和一些在进行数据获取时的需要注意的点,有时候可以通过修改特定的属性从而达到不同的效果。而Get类中的大部分API并没有被提到,因此如果继续需要深入学习的话可以去官网的 API中详细查看Get类中的所有的API。如果上述有错误的地方,还望指出,共勉。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值