Hbase--Scan全局扫描中的过滤器

Hbase过滤器

一·:hbase 过滤器的比较运算符: CompareOp
  • LESS <
  • LESS_OR_EQUAL <=
  • EQUAL =
  • NOT_EQUAL <>
  • GREATER_OR_EQUAL >=
  • GREATER >
  • NO_OP 排除所有
二:HBase 过滤器的比较器(指定比较机制):
  • BinaryComparator 按字节索引顺序比较指定字节数组,采用 Bytes.compareTo(byte[])
  • BinaryPrefixComparator 跟前面相同,只是比较左端的数据是否相同
  • NullComparator 判断给定的是否为空
  • BitComparator 按位比较
  • RegexStringComparator 提供一个正则的比较器,仅支持 EQUAL 和非 EQUAL
  • SubstringComparator 判断提供的子串是否出现在 value 中。
三:过滤器的分类
1.指定扫描
public static void scanTable(String tableNanme,String rowkeyStart,String rowkeyStop,
			String family,String qualifier,long minStamp,long maxStamp,String qualifier2,String age) throws IOException {
		//1.获取表对象
		Table table=connection.getTable(TableName.valueOf(tableNanme));
		//2.创建一个scan对象
		Scan scan=new Scan();
		//2.1指定列族
		//scan.addFamily(family.getBytes());
		//2.2指定列
		//scan.addColumn(Bytes.toBytes(family), qualifier.getBytes());
		//2.3指定时间戳范围
		//2.3.1指定单个时间戳
		//scan.setTimeStamp(minStamp);
		//2.3.2指定时间戳范围(含头不含尾)
		//scan.setTimeRange(minStamp, maxStamp);
		
		//3.指定行键范围,因为底层存储会按行键的范围进行排序,所以可以指定范围
		//scan.setStartRow(rowkeyStart.getBytes());
		//scan.setStopRow(rowkeyStop.getBytes());
		
		//4.扫描全表
		ResultScanner resultScanner=table.getScanner(scan);
		
		//4.解析resultScanner
		for (Result result : resultScanner) {//取出一个个的result
			//5.解析result
			for (Cell cell:result.rawCells()) {
				//6.打印数据
System.out.println("rowkey:"+Bytes.toString(CellUtil.cloneRow(cell))+","+"family:"+Bytes.toString(CellUtil.cloneFamily(cell))+","+"qualifiler:"+Bytes.toString(CellUtil.cloneQualifier(cell))+","+"Value:"+Bytes.toString(CellUtil.cloneValue(cell)));
			}
		}
		//7.关闭表连接
		table.close();
	}
2.比较过滤器:
  • FamilyFilter 针对列族过滤

    /**
    * 构造列族比较器对象
    * 参数1:比较运算符
    * 参数2:比较器(比较规则)
     */
    Filter f1= new FamilyFilter(CompareOp.EQUAL, new BinaryComparator("info01".getBytes()));
    
  • QulifierFilter 列名过滤器

    /**
    * 构造列名比较器对象
    * 参数1:比较运算符
    * 参数2:比较器(比较规则)
     */
    	Filter f2=new QualifierFilter(CompareOp.EQUAL, new BinaryComparator(qualifier2.getBytes()));      final ByteArrayComparable qualifierComparator)
    
  • ValueFilter 列值过滤器

    /**
    * 构造列值比较器对象
    * 参数1:比较运算符
    * 参数2:比较器(比较规则)
     */
    Filter f3=new ValueFilter(CompareOp.LESS_OR_EQUAL,new BinaryComparator(Bytes.toBytes(age)));
    
  • RowFilter 行健过滤器

    /**
    * 构造行键比较器对象
    * 参数1:比较运算符
    * 参数2:比较器(比较规则)
     */
    Filter filter1 = new RowFilter(CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes("user0000"))); 
    
  • TimestampsFilter 时间戳过滤器

    时间戳比较器一般要使用到集合,可以添加一个集合为TimestampsFilter参数

    List<Long> ts = new ArrayList<Long>();
    tss.add(1495398833002l);
    Filter filter1 = new TimestampsFilter(ts);
    scan.setFilter(filter1);
    
  • 过滤器连用

    ​ MUST_PASS_ALL:过滤器都通过
    MUST_PASS_ONE:过滤器只使用一个

    /**
    * 多个过滤器连用
    * 参数1:指定多个过滤器的逻辑计算关系
    * 参数2:指定连用的过滤器
    */
    FilterList f4=new FilterList(Operator.MUST_PASS_ALL, f2,f3);
    

一般的比较过滤器的构造方法的参数

        参数1:
        CompareOp valueCompareOp  指定比较操作符
            > >= < <= == !=
            public enum CompareOp {
            /** less than */
            LESS,//小于
            /** less than or equal to */
            LESS_OR_EQUAL,//小于等于
            /** equals */
            EQUAL,//等于
            /** not equal */
            NOT_EQUAL,//不等于
            /** greater than or equal to */
            GREATER_OR_EQUAL,//大于等于
            /** greater than */
            GREATER,//大于
            /** no operation */
            NO_OP,//不比较
          }
        参数2
        指定比较值
		BinaryComparator  按照字节进行比较
		BinaryPrefixComparator 跟前面相同,只是比较左端的数据是否相同 
		NullComparator 判断给定的是否为空 
		BitComparator 按位比较 
		RegexStringComparator 提供一个正则的比较器,仅支持 EQUAL 和非 EQUAL 
		SubstringComparator 判断提供的子串是否出现在 value 中。 
2.专用过滤器
  • 单列值过滤器 SingleColumnValueFilter ----会返回满足条件的整行

    	/**
    	 * 专用过滤器——值过滤器
    	 */
    	public static void scan_sr(String tablename,String family,String qualifier,String  value,String prefix) throws IOException {
    		//获取表连接
    		Table table=connection.getTable(TableName.valueOf(tablename));
    		//创建扫描对象
    		Scan scan=new Scan();
    		//创建但值过滤器
    		SingleColumnValueFilter sr=new SingleColumnValueFilter(family.getBytes(), qualifier.getBytes(), CompareOp.EQUAL, Bytes.toBytes(value));
    		//sr.setFilterIfMissing(true);
    		//设置扫描器
    		scan.setFilter(sr);
    		//scan.addColumn(family.getBytes(), qualifier.getBytes());
    		//获取全局扫描的结果
    		ResultScanner scanner=table.getScanner(scan);
    		//遍历获取
    		for (Result result : scanner) {
    			for (Cell cell : result.rawCells()) {
    				System.out.println("rowkey:"+Bytes.toString(CellUtil.cloneRow(cell))+","+"family:"+Bytes.toString(CellUtil.cloneFamily(cell))+","
    						+"qualifiler:"+Bytes.toString(CellUtil.cloneQualifier(cell))+","+
    						"Value:"+Bytes.toString(CellUtil.cloneValue(cell)));
    			}
    		}
    	}
    

    关于单值过滤器SingleColumnValueFilter的坑:如果仅仅只使用单值过滤器返回不是我们想要的结果,例如有如下数据:

    ROW                                        COLUMN+CELL                                                                                                               
     000001                                    column=info01:name, timestamp=1571814795977, value=pikce1_2                                                               
     000001                                    column=info02:age, timestamp=1571915607101, value=11                                                                      
     000002                                    column=info01:age, timestamp=1571915577077, value=22                                                                      
     000002                                    column=info01:name, timestamp=1571814796770, value=pikce2_2                                                               
     000002                                    column=info02:age, timestamp=1571915591755, value=10                                                                      
     000003                                    column=info01:age, timestamp=1571887612984, value=12                                                                      
     000003                                    column=info01:name, timestamp=1571815672698, value=pick02                                                                 
     000003                                    column=info02:age, timestamp=1571887633662, value=12                                                                      
     000004                                    column=info01:age, timestamp=1571916710317, value=22                                                                      
     000004                                    column=info02:age, timestamp=1571887661213, value=22                                                                      
     000004                                    column=info02:name, timestamp=1571889126588, value=20                                                                     
     000005                                    column=info01:age, timestamp=1571916718840, value=22                                                                      
     100005                                    column=info01:age, timestamp=1571918114145, value=22                                                                      
     100006                                    column=info01:age, timestamp=1571924100668, value=22                                                                      
    

    使用单值过滤器:

    SingleColumnValueFilter sr=new SingleColumnValueFilter("info01".getBytes(), "age".getBytes(), CompareOp.EQUAL, Bytes.toBytes("22"));
    scan.setFilter(sr);
    

    出来的结果如下,会发现离我们理想的结果偏差很大,多了一些我们并不想要的结果

    rowkey:000001,family:info01,qualifiler:name,Value:pikce1_2
    rowkey:000001,family:info02,qualifiler:age,Value:11
    rowkey:000002,family:info01,qualifiler:age,Value:22
    rowkey:000002,family:info01,qualifiler:name,Value:pikce2_2
    rowkey:000002,family:info02,qualifiler:age,Value:10
    rowkey:000004,family:info01,qualifiler:age,Value:22
    rowkey:000004,family:info02,qualifiler:age,Value:22
    rowkey:000004,family:info02,qualifiler:name,Value:20
    rowkey:000005,family:info01,qualifiler:age,Value:22
    rowkey:100005,family:info01,qualifiler:age,Value:22
    rowkey:100006,family:info01,qualifiler:age,Value:22
    

    如何解决的:scan的时候还需要再加上过滤,如下

    scan.addColumn(family.getBytes(), qualifier.getBytes());
    

    加上过滤之后的结果:

    rowkey:000002,family:info01,qualifiler:age,Value:22
    rowkey:000004,family:info01,qualifiler:age,Value:22
    rowkey:000005,family:info01,qualifiler:age,Value:22
    rowkey:100005,family:info01,qualifiler:age,Value:22
    rowkey:100006,family:info01,qualifiler:age,Value:22
    
  • 单列值排除器 SingleColumnValueExcludeFilter -----返回排除了该列的结果

    //创键单值排除器
    		SingleColumnValueExcludeFilter ser=new SingleColumnValueExcludeFilter(family.getBytes(), qualifier.getBytes(), CompareOp.EQUAL, Bytes.toBytes(value));
    		
    

    使用单列值排除器 SingleColumnValueExcludeFilter的坑:由于使用的排除器是返回的不满足给出的条件的数据,所以这时就不能再scan的时候添加过滤,再添加了就不会有结果返回来

  • 行键前缀过滤器 PrefixFilter----针对行键

    //创键单值排除器
    PrefixFilter ser=new PrefixFilter(prefix.getBytes());
    
  • 列前缀过滤器 ColumnPrefixFilter

    //创建行键前缀过滤器
    PrefixFilter pr=new PrefixFilter(Bytes.toBytes(prefix));
    scan.setFilter(pr);
    
  • 分页过滤器 PageFilter

public static void Scan_page(String tablename,String startRow,int pageSize) throws IOException {
		Table table=connection.getTable(TableName.valueOf(tablename));
		//创建扫描器对象
		Scan scan=new Scan();
		//创建分页过滤器,第一步设置起始位置,第二部设置每页的条数
		//scan.setStartRow(startRow.getBytes());
		PageFilter page=new PageFilter(pageSize);
		
		//创建扫描器
		scan.setFilter(page);
		//获取扫描结果
		ResultScanner scanner=table.getScanner(scan);
		//遍历扫描结果
		for (Result result : scanner) {
			for (Cell cell : result.rawCells()) {
System.out.println("rowkey:"+Bytes.toString(CellUtil.cloneRow(cell))+","+"family:"+Bytes.toString(CellUtil.cloneFamily(cell))+","+"qualifiler:"+Bytes.toString(CellUtil.cloneQualifier(cell))+","+"Value:"+Bytes.toString(CellUtil.cloneValue(cell)));
			}
		}
	}

分页过滤器测试如下:

Scan_page("HbaseAPI:HbaseAPI01", "000001",1);
运行的结果如下:
rowkey:000001,family:info01,qualifiler:name,Value:pikce1_2
rowkey:000001,family:info02,qualifiler:age,Value:11
Scan_page("HbaseAPI:HbaseAPI01", "000001",2);
运行的结果如下:
rowkey:000001,family:info01,qualifiler:name,Value:pikce1_2
rowkey:000001,family:info02,qualifiler:age,Value:11
rowkey:000002,family:info01,qualifiler:age,Value:22
rowkey:000002,family:info01,qualifiler:name,Value:pikce2_2
rowkey:000002,family:info02,qualifiler:age,Value:10
Scan_page("HbaseAPI:HbaseAPI01", "000001",3);
运行结果如下:
rowkey:000001,family:info01,qualifiler:name,Value:pikce1_2
rowkey:000001,family:info02,qualifiler:age,Value:11
rowkey:000002,family:info01,qualifiler:age,Value:22
rowkey:000002,family:info01,qualifiler:name,Value:pikce2_2
rowkey:000002,family:info02,qualifiler:age,Value:10
rowkey:000003,family:info01,qualifiler:age,Value:12
rowkey:000003,family:info01,qualifiler:name,Value:pick02
rowkey:000003,family:info02,qualifiler:age,Value:12

综合上面的测试可以发现,PageFilter page=new PageFilter(pageSize),传入的参数page在分页的时候就是代表了行键的个数,并不是代表有几条数据,每一页显示的数据个数是由行键决定的,并且是行键由小到大排序的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值