HBase的分页-PageFilter

使用PageFilter分页效率比较低,应为每次都须要扫描前面的数据,直到扫描到所须要查的数据,可是查询下一页的时候能够直接利用上一页的rowkey来直接查出java

Filter是定义每次scan得出多少条记录, 
下面看用PageFilter实现分页的(最好使用rowksy,不建议使用过滤器,过滤器效率过低,设计表的时候设计一个好的rowkey能够带来好多的便利的条件)apache

代码记录:dom

package hbasepage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.FilterList;
import org.apache.hadoop.hbase.filter.PageFilter;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;

public class Pager {
    public static Configuration configuration;
    static {
        configuration = HBaseConfiguration.create();
        configuration.set("hbase.zookeeper.property.clientPort", "2181");
        configuration.set("hbase.zookeeper.quorum",
                "192.168.10.24,192.168.10.29,192.168.10.64");
        configuration.set("hbase.master", "192.168.10.120:60000");
    }
    private String tableName;
    private static HTable hTable;
    private static String startRow = null;
    private static List list = null;

    public Pager(String tableName) {

        try {
            this.hTable = new HTable(configuration, tableName.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static List getLast(int pageNum, int pageSize){
        getPage(pageNum-1,pageSize);
        return null;
    }
    /**
     * 取得下一页 这个类是接着getPage来用
     * @param pageSize 分页的大小
     * @return  返回分页数据
     */
    public static List getNext(int pageSize) throws Exception{
        Filter filter = new PageFilter(pageSize +1);
        Scan scan = new Scan();
        scan.setFilter(filter);
        scan.setStartRow(startRow.getBytes());
        ResultScanner result = hTable.getScanner(scan);
        Iterator iterator = result.iterator();
        list = new ArrayList<>();
        int count = 0;
        for(Result r:result){
            count++;
            if (count==pageSize + 1) {
                startRow = new String(r.getRow());

                scan.setStartRow(startRow.getBytes());
                System.out.println("startRow" + startRow);
                break;
            }else{
                list.add(r);
            }
            startRow = new String(r.getRow());
            System.out.println(startRow);
            //把 r的全部的列都取出来     key-value age-20
            System.out.println(count);
        }
        return list;

    }
    // pageNum = 3 pageSize = 10
    public static void getPage(int pageNum, int pageSize) {
        System.out.println("hahha");
        // int pageNow = 0;
        // TODO 这个filter究竟是干吗的?
        Filter page = new PageFilter(pageSize + 1);
        int totalSize = pageNum * pageSize;
        Scan scan = new Scan();
        scan.setFilter(page);
        //pageNum = 3   须要扫描3页
        for (int i = 0; i < pageNum; i++) {

            try {
                ResultScanner rs = hTable.getScanner(scan);
                int count = 0;
                for (Result r : rs) {
                    count++;
                    if (count==pageSize + 1) {
                        startRow = new String(r.getRow());

                        scan.setStartRow(startRow.getBytes());
                        System.out.println("startRow" + startRow);
                        break;
                    }
                    startRow = new String(r.getRow());
                    System.out.println(startRow);
                    //把 r的全部的列都取出来     key-value age-20
                    for (KeyValue keyValue : r.list()) {
                        System.out.println("列:"
                                + new String(keyValue.getQualifier()) + "====值:"
                                + new String(keyValue.getValue()));
                    }
                    System.out.println(count);


                }
                if (count < pageSize) {
                    break;
                }

            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

 

下面写一点经常使用的fiter过滤器oop

HBase为筛选数据提供了一组过滤器,经过这个过滤器能够在HBase中的数据的多个维度(行,列,数据版本)上进行对数据的筛选操做,也就是说过滤器最终可以筛选的数据可以细化到具体的一个存储单元格上(由行键,列明,时间戳定位)。一般来讲,经过行键,值来筛选数据的应用场景较多。性能

  1. RowFilter:筛选出匹配的全部的行,对于这个过滤器的应用场景,是很是直观的:使用BinaryComparator能够筛选出具备某个行键的行,或者经过改变比较运算符(下面的例子中是CompareFilter.CompareOp.EQUAL)来筛选出符合某一条件的多条数据,如下就是筛选出行键为row1的一行数据:
Filter rf = new RowFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(“row1”))); // OK 筛选出匹配的全部的行
  1. PrefixFilter:筛选出具备特定前缀的行键的数据。这个过滤器所实现的功能其实也能够由RowFilter结合RegexComparator来实现,不过这里提供了一种简便的使用方法,如下过滤器就是筛选出行键以row为前缀的全部的行:
Filter pf = new PrefixFilter(Bytes.toBytes(“row”)); // OK 筛选匹配行键的前缀成功的行
  1. KeyOnlyFilter:这个过滤器惟一的功能就是只返回每行的行键,值所有为空,这对于只关注于行键的应用场景来讲很是合适,这样忽略掉其值就能够减小传递到客户端的数据量,能起到必定的优化做用:
Filter kof = new KeyOnlyFilter(); // OK 返回全部的行,但值全是空
  1. RandomRowFilter:从名字上就能够看出其大概的用法,本过滤器的做用就是按照必定的概率(<=0会过滤掉全部的行,>=1会包含全部的行)来返回随机的结果集,对于一样的数据集,屡次使用同一个RandomRowFilter会返回不通的结果集,对于须要随机抽取一部分数据的应用场景,可使用此过滤器:
Filter rrf = new RandomRowFilter((float) 0.8); // OK 随机选出一部分的行
  1. InclusiveStopFilter:扫描的时候,咱们能够设置一个开始行键和一个终止行键,默认状况下,这个行键的返回是前闭后开区间,即包含起始行,单不包含中指行,若是咱们想要同时包含起始行和终止行,那么咱们可使用此过滤器:
Filter isf = new InclusiveStopFilter(Bytes.toBytes(“row1”)); // OK 包含了扫描的上限在结果以内
  1. FirstKeyOnlyFilter:若是你只想返回的结果集中只包含第一列的数据,那么这个过滤器可以知足你的要求。它在找到每行的第一列以后会中止扫描,从而使扫描的性能也获得了必定的提高:
Filter fkof = new FirstKeyOnlyFilter(); // OK 筛选出第一个每一个第一个单元格
  1. ColumnPrefixFilter:顾名思义,它是按照列名的前缀来筛选单元格的,若是咱们想要对返回的列的前缀加以限制的话,可使用这个过滤器:
Filter cpf = new ColumnPrefixFilter(Bytes.toBytes(“qual1”)); // OK 筛选出前缀匹配的列
  1. ValueFilter:按照具体的值来筛选单元格的过滤器,这会把一行中值不能知足的单元格过滤掉,以下面的构造器,对于每一行的一个列,若是其对应的值不包含ROW2_QUAL1,那么这个列就不会返回给客户端:
Filter vf = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(“ROW2_QUAL1”)); // OK 筛选某个(值的条件知足的)特定的单元格
  1. ColumnCountGetFilter:这个过滤器来返回每行最多返回多少列,并在遇到一行的列数超过咱们所设置的限制值的时候,结束扫描操做:
Filter ccf = new ColumnCountGetFilter(2); // OK 若是忽然发现一行中的列数超过设定的最大值时,整个扫描操做会中止
  1. SingleColumnValueFilter:用一列的值决定这一行的数据是否被过滤。在它的具体对象上,能够调用setFilterIfMissing(true)或者setFilterIfMissing(false),默认的值是false,其做用是,对于我们要使用做为条件的列,若是这一列自己就不存在,那么若是为true,这样的行将会被过滤掉,若是为false,这样的行会包含在结果集中。
SingleColumnValueFilter scvf = new SingleColumnValueFilter( 
Bytes.toBytes(“colfam1”), 
Bytes.toBytes(“qual2”), 
CompareFilter.CompareOp.NOT_EQUAL, 
new SubstringComparator(“BOGUS”)); 
scvf.setFilterIfMissing(false); 
scvf.setLatestVersionOnly(true); // OK
  1. SingleColumnValueExcludeFilter:这个与10种的过滤器惟一的区别就是,做为筛选条件的列的不会包含在返回的结果中。
  2. SkipFilter:这是一种附加过滤器,其与ValueFilter结合使用,若是发现一行中的某一列不符合条件,那么整行就会被过滤掉:
Filter skf = new SkipFilter(vf); // OK 发现某一行中的一列须要过滤时,整个行就会被过滤掉
  1. WhileMatchFilter:这个过滤器的应用场景也很简单,若是你想要在遇到某种条件数据以前的数据时,就可使用这个过滤器;当遇到不符合设定条件的数据的时候,整个扫描也就结束了:
Filter wmf = new WhileMatchFilter(rf); // OK 相似于Python itertools中的takewhile
  1. FilterList:用于综合使用多个过滤器。其有两种关系:FilterList.Operator.MUST_PASS_ONE和FilterList.Operator.MUST_PASS_ALL,默认的是FilterList.Operator.MUST_PASS_ALL,顾名思义,它们分别是AND和OR的关系,而且FilterList能够嵌套使用FilterList,使咱们可以表达更多的需求:
List filters = new ArrayList(); 
filters.add(rf); 
filters.add(vf); 
FilterList fl = new FilterList(FilterList.Operator.MUST_PASS_ALL, filters); // OK 综合使用多个过滤器, AND 和 OR 两种关系

以上,是对于HBase内置的过滤器的部分总结优化

相关文章
相关标签/搜索