1. 程式人生 > >HBase偽快速分頁查詢

HBase偽快速分頁查詢

    之前有兩個功能,都是查詢歷史資料的一個分頁查詢,系統剛上線的時候,沒有太多的資料,就一直扔在mysql裡面,後來裡面資料上億之後,就查不到了,而且資料還在以指數級增長方式上報,後來,這部分業務單獨遷移到hbase叢集去存放,之前頁面的查詢也改查hbase了。但是hbase對分頁查詢這種東西支援不好,如果按照以往查詢mysql的思路,查詢出一個總的count,再查詢出這一頁的資料,這種方式去查詢hbase,那麼如果你仔細去跟程式碼計算時間的話,你會發現hbase去查count,無論哪種方式,都會引起全表掃描,是非常慢的。整個頁面加載出來,看了下響應事件,大概要45s,等的我都喝了兩杯茶了。

   so,我想了個比較偽的分頁查詢方法,去掉查詢count操作,值查詢一頁資料:

public Page<BatteryData> findBatterHisData(BatteryHisDto dto)throws Exception {
        Page<BatteryData> dataPage=new Page<BatteryData>();
        List<BatteryData> dataList=new ArrayList<>();
        int totalSize=0;
        Table table=runner.getTable(tableName);
        Scan dataScan=new Scan();
        ResultScanner dataScanner=null;
        List<Filter> dataFilters = new ArrayList<Filter>();
        if(StringUtils.isNotBlank(dto.getBatteryNo())){//電池組編號過濾
            Filter filter=new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(dto.getBatteryNo()+"_"));
            dataFilters.add(filter);
        }
        Filter pageFilter=new PageFilter(dto.getPage()+dto.getPageSize());
        dataFilters.add(pageFilter);
        FilterList dataFilterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, dataFilters);
        dataScan.setFilter(dataFilterList);
        dataScanner=table.getScanner(dataScan);
        dataList= rsh.handle(tableName,dataScanner);
        if(dataList==null || dataList.size()<1){
            dataPage.setTotalCount(0);
            dataPage.setResult(null);
            return dataPage;
        }
        int startNo = dto.getPage();
        int endNo=startNo+dto.getPageSize();
        dataPage.setTotalCount(dto.getPage()+dto.getPageSize()+1);
        dataPage.setResult(dataList.subList(startNo,endNo));
        table.close();
        return dataPage;
	}



     因為使用者關注的,通常是前幾頁的資料,所有我每次查詢的時候,返回總頁數,都返回個隨便的數(跟前端的分頁表格配合,實際上,我的前端只提供了上下分頁,哈哈),然後查詢有限條的資料,通常hbase表都是上億甚至是百億的,所以,使用者時不太可能通過只點擊上一頁下一頁,這樣點到我最後一頁的,可以放心了。最多他點個幾千頁,也就手疼到不行了。這樣下來,響應速度控制在800ms內,無壓力。

    PS,看到很多網友通過rowkey去做分頁,具體思路是,每次記錄下起始的rowkey和結束的rowkey,然後根據rowkey搜尋,這樣也是很快的,個人認為,也ok。