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內置的過濾器的部分總結優化

相關文章
相關標籤/搜索