SHDP--Working with HBase(三)之HBase+Phoenix實現分頁


先簡單講講只用HBase來實現分頁的思路:
HBase利用scan來掃描表,通過startKey,stopKey來確定掃描范圍,在需要進行分頁時可以結合HBase提供的PagefFilter過濾掃描的行數使scan返回N條數據達到分頁的目的(N為每頁的記數),此時有以下兩種方案達可以達到分頁目的:
 
1. 在得到scan結果后把上一頁的最后一條數據作為scan下一頁時的startKey,但是此時下一頁的數據在傳到客戶端時就要排除第一條數據了(因為第一條的數據是上一頁的)
 
2.在每次scan時多查詢一條數據(即返回N+1)作為下一頁的startKey
 
以上的方案存有個大前提:HBase的RowKey必須是序列增長(類似1,2,3,....)的,否則的話雖然能定位到下一頁的startkey,但是當我要查詢上一頁/上N頁時就不能夠定位到此時的startkey了。
 
所以解決這個大前提的方案就是 添加一個序列ID到RowKey中來幫助起始鍵定位到對應偏移量的位置,但是當你的RowKey存在其他字符(如漢字)時就不能簡單的將序列ID添加到RowKey了。(所以僅僅通過HBase來實現分頁還是比較麻煩的,特別是RowKey比較復雜的時候)
 
下面是具體的實現方案:
 
項目場景:按條件查詢並實現分頁(如按澳門,三亞,2016-01-02查詢並分頁)
 
這里我選擇使用Phoenix來操作HBase,原因是 對於簡單條件的查詢Phoenix速度快,並且Phoenix提供了生成序列ID的方法,對於熟悉SQL語句的開發者來說可以很好的提高開發效率。
 
步驟:(HBase中存在TRAVEL表)
 
1.在Phoenix中為TRAVEL表創建視圖TRAVEL
CREATE VIEW TRAVEL (ROWKEY VARCHAR PRIMARY KEY,INFO.SP VARCHAR,INFO.EP VARCHAR,INFO.ST VARCHAR,INFO.ET VARCHAR);
 (INFO為HBase表TRAVEL的列族名)
視圖TRAVEL中的一段數據如下:
 
2.建立sequence(序列)
CREATE SEQUENCE SEQ;
 
3.在Phoenix中新建表PAGETRAVEL
CREATE TABLE TRAVEL (ROWKEY VARCHAR PRIMARY KEY,INFO.SP VARCHAR,INFO.EP VARCHAR,INFO.ST VARCHAR,INFO.ET VARCHAR,PAGEID BIGINT);
(字段PAGEID就是幫助起始健定位對應偏移量的分頁ID)

 

4.通過Phoenix的UPSERT SELECT將視圖TRAVEL中的數據全部插入到PAGETRAVEL表中
UPSERT INTO PAGETRAVEL SELECT ROWKEY,SP,EP,ST,ET,NEXT VALUE FOR SEQ FROM TRAVEL;
PAGETRAVEL表中的部分數據如下:    
有了PAGEID后就可以輕易的確定每頁起始鍵對應的偏移量。
 
5.得到每頁起始鍵的偏移量(PAGEID)
SELECT PAGEID FROM TRAVEL WHERE ROWKEY LIKE '澳門三亞%' AND ST >= '2016-01-02';
 
6.分頁查詢
SELECT * FROM TRVELS WHERE PAGEID > PAGEID*(PAGENUM-1)*N ORDER BY PAGEID LIMIT N WHERE ROWKEY LIKE '澳門三亞%';

(PAGENUM為當前頁數)

 

關鍵代碼實現:

public List findPageRecords(int currentPageNum, int pageSize,String ST,String SP,String EP) {
//得到每頁起始鍵的偏移量,第一個參數為SQL語句,第二個參數為返回值類型的Class對象,第三個參數為占位符值(為可變參數) int startkey = jdbcTemplate.queryForObject("SELECT * FROM TRAVELS WHERE ST >= ? AND ROWKEY LIKE ? LIMIT 1",Integer.class,ST,SP+EP+"%"); //第一個參數為SQL語句,第二參數的RowMapper將每一行結果映射成一個Java對象,方便將其他封裝到JavaBean中,第三個參數為占位符值(為可變參數) List<Travel> travels = jdbcTemplate.query("SELECT * FROM TRAVELS where PAGEID >= ? AND ST >= ? AND ROWKEY LIKE ? limit 8", new RowMapper<Travel>() { public Travel mapRow(ResultSet rs, int rowNum) throws SQLException { Travel travel = new Travel(); travel.setROWKEY(rs.getString("ROWKEY")); travel.setURL(rs.getString("URL")); travel.setSP(rs.getString("SP")); travel.setEP(rs.getString("EP")); travel.setST(rs.getString("ST")); travel.setET(rs.getString("ET")); travel.setSIGHTS(rs.getString("SIGHTS")); travel.setALLDATE(rs.getString("ALLDATE")); travel.setHOTEL(rs.getString("HOTEL")); travel.setTOTALPRICE(rs.getString("TOTALPRICE")); travel.setTRAFFIC(rs.getString("TRAFFIC")); travel.setTRAVELTYPE(rs.getString("TRAVELTYPE")); travel.setSUPPLIER(rs.getString("SUPPLIER")); return travel; } },startkey+(currentPageNum - 1)*pageSize,ST,SP+EP+"%"); return travels; }

 

總結:通過與Spring JDBC的集成,利用Phoneix可以很輕易的實現HBase分頁極大地提高開發效率,並且Phoenix還提供了二級索引的功能。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM