3.基本命令之过滤器Filter

10.过滤器Filter

​ 在Hbase中,get 和 scan 操作都可以使用过滤器来设置输出的范围,类似 SQL 里的 Where 查询条件。

​ 使用 show_filter 命令可以查看当前 HBase 支持的过滤器类型,如下图所示。
在这里插入图片描述

使用上述过滤器时,一般需要配合比较运算符或比较器使用,如下面两个表所示。
在这里插入图片描述

使用过滤器的语法格式如下所示:

​ scan ‘表名’, { Filter => "过滤器(比较运算符, ‘比较器’) }

​ 在上述语法中,Filter=> 指明过滤的方法,整体可用大括号引用,也可以不用大括号。过滤的方法用双引号引用,而比较方式用小括号引用。

行键过滤器

在这里插入图片描述

列族与列过滤器

​ 针对列族进行过滤的过滤器为 FamilyFilter,其语法结构与 RowFilter 类似,不同之处在于 FamilyFilter 是对列族名称进行过滤的。

​ 例如,以下命令扫描Student表显示列族为 Grades 的行。

​ scan ‘Student’, FILTER=>" FamilyFilter(= , ‘substring:Grades’)"

​ 针对列的过滤器如下表所示,这些过滤器也需要结合比较运算符和比较器进行列族或列的扫描过滤。
在这里插入图片描述

​ 上表中 QualifierFilter 和 ColumnPrefixFilter 过滤效果类似,只是 ColumnPrefixFilter 无须结合运算符和比较器即可完成字符串前缀的过滤。

​ MultipleColumnPrefixFilter 过滤器是对 ColumnPrefixFilter 的延伸,可以一次过滤多个列前缀。

​ ColumnRangeFilter过滤器则可以扫描出符合过滤条件的列范围,起始和终止列名用单引号引用,true 和 false 参数可指明结果中包含的起始或终止列。

值过滤器

在 HBase 的过滤器中也有针对单元格进行扫描的过滤器,即值过滤器,如下表所示。
在这里插入图片描述

​ ValueFilter 过滤器可以利用 get 和 scan 方法对单元格进行过滤,但是使用 get 方法时,需要指定行键。

​ SingleColumnValueFilter 和 SingleColumnValueExcludeFilter 过滤器扫描的结果是相反的, 都需要在过滤条件中指定列族和列的名称。

其他过滤器

​ 还有一些其他的过滤器,其过滤方式和示例如下表所示。
在这里插入图片描述

​ ColumnCountGetFilter 过滤器限制每个逻辑行返回多少列,一般不用在 scan 方法中,Timestamps Filter 匹配相同时间戳的数据。

​ InclusiveStopFilter过滤器设置停止行,且包含停止的行,上表中示例最终展示数据为行键 0001〜0003 范围内的数据。PageFilter 设置每页最多显示多少逻辑行, 示例中显示三个逻辑行。

​ ColumnPaginationFilter过滤器对一个逻辑行的所有列进行分页显示。

#scan 使用过滤器 行健前缀过滤器,只有这一个有属性
scan 'test2:emp', {ROWPREFIXFILTER => '2'}

#scan 使用空值行健过滤器,只返回行健
scan 'test2:emp',{FILTER=>'KeyOnlyFilter()'}
scan 'test2:emp',{FILTER =>org.apache.hadoop.hbase.filter.KeyOnlyFilter.new()}

#scan 使用行健过滤器,binary: 帮助数据类型转化
scan 'test2:emp',{FILTER=>"RowFilter(>,'binary:1')"}
scan 'test2:emp',{FILTER =>"RowFilter(!=,'binary:10001')"}

#scan 使用列名过滤器
scan 'test2:emp',{FILTER =>"QualifierFilter(>=,'binary:baseinfo:name')"}
#scan 列名前缀过滤器
scan 'test2:emp',{FILTER =>"ColumnPrefixFilter('name')"}


#scan 使用子串过滤器
scan 'test2:emp',{FILTER =>"ValueFilter(=,'binary:zhao')"}
#scan 使用多种过滤器进行条件结合
scan 'test2:emp',{FILTER =>"(ValueFilter(=,'binary:hello')) OR (RowFilter (>,'binary:10'))"}

#scan 使用page过滤器,限制每页展示数量
scan 'test2:emp',{STARTROW=>'1',ENDROW=>'5',FILTER =>'PageFilter(3)'}

#scan 使用行健过滤器,进行正则表达式的匹配
scan 'test2:emp', {FILTER => org.apache.hadoop.hbase.filter.RowFilter.new(org.apache.hadoop.hbase.filter.CompareFilter::CompareOp.valueOf('EQUAL'),org.apache.hadoop.hbase.filter.RegexStringComparator.new('.*1.*'))}

4.Hbase存储结构

​ 系统表
​ hbase:namespace 命名空间,逻辑抽象分组,类似于关系型数据库里面的database。
​ hbase:meta META表,存储自定义表的Region分布。
​ 注意:既然是表,数据量达到一定程度,也会分区。

​ 因此Hbase设计中还存在一个叫做-ROOT-表(新版本中是以文件的形式存储在Zookeeper中)的来记录META表的Region分布情况。

例如:
		#建表
		create 'bd1901:emp1','f1','f2'
		create 'bd1901:emp2','f1','f2',SPLITS=>['1000','2000','3000']
		#查询meta数据
		scan 'hbase:meta',{COLUMNS=>'info:server',LIMIT=>5}
		scan 'hbase:meta',{ROWPREFIXFILTER => '5'}
案例:
	数据准备:
		1.建表语句:
			create 'bd1901:test2','cf1',SPLITS=>['1000','2000','3000','4000']
			该表预定义分区为5--->5条数据保存到META表(很大,分区)
            -ROOT-表(不会再进行分区,新版本是直接存储在ZK中文件)
		2.META表数据存储格式样例:
			RowKey        			info:Server 	info:regionInfo
			table,StartKey,Time 	IP  			startKey-endKey

			数据为:
			abc:test1,,T 			cmm1:16020       -
			.......
			bd1901:test2,,T  		cmm1:16023       -1000
			bd1901:test2,1000,T 	cmm1:16022 		1000-2000
			bd1901:test2,2000,T 	cmm1:16020 		2000-3000
			bd1901:test2,3000,T 	cmm1:16023 		3000-4000
			bd1901:test2,4000,T 	cmm1:16022 		4000-
			bd1901:test3,,T 		cmm1:16022      -10
			bd1901:test3,10,T 		cmm1:16023 		10-30
			bd1901:test3,30,T 		cmm1:16020 		30-
			hbase:namespace,,T 		cmm1:16020      -
			.......
			ztest:emp1,,T 			cmm1:16023      -
		3.ROOT文件数据存储格式样例:
			RowKey  startRowKey-endRowKey				IP
			1   	abc:test1,,T-bd1901:test2,2000,T 	cmm1:16020 
			2   	bd1901:test2,3000,T-ztest:emp1,,T 	cmm1:16022
		4.client向Zookeeper发送读请求
			例如:
				get 'bd1901:test3','20'
				1.client优先从本地缓存中读取数据
				2.缓存中没有找到的情况下,会根据二级寻址方式查找该条数据位于哪一个Region,获取该HRegion所在的HRegionServer服务器的位置信息(即IP地址)。
				3.Client向数据分区服务器发送读请求
					1.优先从MemStore中读取数据(内存缓冲 64M)
						写进去的数据(刚insert之后立刻select)
					2.优先从BlockCache中读取数据 块缓存
						会将经常检索的数据以及该数据前后的数据都会存储到该块缓存中,以提高查询效率。
					3.如果以上两个内存中都没有读取到数据,则借助于IO操作从HDFS文件中读取数据。

5.二级寻址

​ Hbase旧版本寻找某一个表的某一个RowKey对应数据的采用的是三级寻址。
​ 新版本更新为二级寻址。
​ 1.Client向Zookeeper发送读/写请求,读取Zookepper中的/hbase/meta-region-server节点信息(即-ROOT-表),获取到META表中该表该RowKey所在HRegionServer的位置信息。
​ 2.Client向该位置信息发送读/写请求,读取META表信息,进一步获取该表该RowKey所对应的HRegionServer的位置信息。
​ 所谓的三级寻址,即-ROOT-表存储在HRegionServer中,需要先借助于Zookeeper查找-ROOT-表的位置信息,再执行以上两步。

6.基本命令

1.热点问题

​ 读写操作集中在某几个Region中,就会造成热点问题。
​ 解决办法:

​ 1.建表时预定义分区(根据实际数据量的预估表分区个数)
​ 2.RowKey设置为随机产生(使用算法生成 hash,md5等)

2.写数据操作

put '命名空间:表名','RowKey','列族:列','值'[,'时间戳’]
​ 1.按照二级寻址方式查找写数据对应的HRegionServer位置信息
​ 2.将数据写入到MemStore以及WAL(Write Ahead Log预写式日志,也叫做HLog)两个地方,全部写入完成,写操作完成。
​ 3.MemStore中默认可以缓存的数据大小为64M,数据写满之后,会被flush到HFile文件中。
​ 4.当StoreFile文件数达到一定量之后,会将多个StoreFile合并为一个大的StoreFile。
​ 5.当单个StoreFile大小达到一个阀值之后,会触发此Region的分裂操作。
​ 6.一分为二,父Region下线,两个子Region上线,ZK通知HMaster。
​ 7.单个Region处理的读数据会被分流到两个Region中进行处理。
​ 8.写数据仍然只能有一个Region负责(参考热点问题,RowKey值会进行排序存储)。

3.读数据操作

​ 参照4.4步骤

	#获得某一个特定值
		get '命名空间:表名','RowKey','列族:列'
	#获得前3个版本的数据
		get '命名空间:表名','RowKey',{COLUMN=>'列族:列',VERSIONS=>3}
	#获得某个时间段数据,不一定是时间最新的数据
		get '命名空间:表名','RowKey',{TIMERANGE=>[1479371084728, 1479373228331]}
	#scan 扫描某张表 select * 
		scan '命名空间:表名'
	#scan 扫描 表中某一列
		scan '命名空间:表名',{COLUMNS=>'列族:列'}
	#scan 使用limit 进行行数限制
		scan '命名空间:表名',{COLUMNS=>'列族:列',LIMIT=>5}
	#scan 指定从某一行开始扫描
		scan '命名空间:表名',{COLUMNS=>'列族:列',LIMIT=>5,STARTROW=>'20001'}
	#scan 扫描所有版本
		scan '命名空间:表名','列族:列',{VERSIONS=>5}

	#在hbase 对于hfile没有进行过合并操作之前
	#scan 超出版本限制也能访问到
		scan '命名空间:表名','列族:列',{VERSIONS=>5,RAW=>true}

	#scan 使用过滤器 行健前缀过滤器,只有这一个有属性
		scan '命名空间:表名', {ROWPREFIXFILTER => '条件'}

	#scan 使用空值行健过滤器,只返回行健(结合HbaseAPI查看Hbase支持的过滤器)
		scan '命名空间:表名',{FILTER=>'KeyOnlyFilter()'}
		在hbase shell客户端表示hbase支持的过滤器的构造参数规则如下:
			1 数值  数字
			2 CompareFilter.CompareOp   比较符  > <
			3 ByteArrayComparable  'binary:1000'    
			4 byte[]   '字符'
     例如:
      1.#scan 使用行健过滤器,binary: 帮助数据类型转化
      scan '命名空间:表名',{FILTER =>"RowFilter(!=,'binary:10001')"}
      2.#scan 使用列名过滤器
      scan '命名空间:表名',{FILTER =>"QualifierFilter(>=,'binary:baseinfo:name')"}
      3.#scan 使用子串过滤器
      scan '命名空间:表名',{FILTER =>"ValueFilter(=,'binary:zhao')"}
      4.#列名前缀过滤器
      scan '命名空间:表名',{FILTER =>"ColumnPrefixFilter('name')"}
      5.#scan 使用多种过滤器进行条件结合
      scan '命名空间:表名',{FILTER =>"(ValueFilter(=,'binary:hello')) OR (RowFilter (>,'binary:10'))"}
      6.#scan 使用page过滤器,限制每页展示数量
      scan '命名空间:表名',{FILTER =>org.apache.hadoop.hbase.filter.KeyOnlyFilter.new()}
      7.#scan 使用行健过滤器,进行正则表达式的匹配
      scan '命名空间:表名', {FILTER => RowFilter.new(CompareFilter::CompareOp.valueOf('EQUAL'),RegexStringComparator.new('.*ll.*'))}

4.删除数据操作

格式:delete <table>, <rowkey>,  <family:column> , <timestamp>
delete 't1','rowkey001','f1:col1’
truncate <table>

删除数据不是直接将数据删除,而是将数据标记为墓碑标记。被标记为墓碑标记的数据只有当Hbase出现大合并的时候,才会将该数据删除。

1.小合并,读取完整一行,可能需要很多HFile,把这些Hfile合并成一个HFile,提高了读取一行的速度,小合并是轻量级的,可以频繁操作(hbase自身控制)。

	Region
		Store(CF1)          
		1个MemStore

		*StoreFile(HFile)
		HFile1  
			RowKey','CF:Q,value1  value2
			   value3
		HFile2   
			RowKey','CF:Q2,value2
		HFile3 HFile4 HFile5
			....
	put '表','RowKey','CF:Q','value1' 
	put '表','RowKey','CF:Q2','value2' 
	put '表','RowKey','CF:Q3','value3' 

	get '表','RowKey' 

2.大合并,把一个列族的所有HFile合并成一个文件,便于浏览该列族所有内容,大合并是重量级的,不要经常使用。
大合并会清除以下三类数据:
1.被标记为墓碑的数据
2.TTL到期的数据
3.超过版本限制的数据
major_compact ‘命名空间:表名’[,‘列族:列名’]

5.移动region

​ move ‘ENCODED_REGIONNAME’, ‘SERVER_NAME’
​ #第一个参数指的是region最后一部分编号(逗号分隔每部分)
​ move ‘a39dc69bd00d19e556ae17e4aeb1ebe1’,‘datanode02,16020,1479354142616’

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐