最近在做基于hbase的项目,考虑到如果在页面上有可供选择跳转到多少页的选项,如果跳转的页面值比较大,数据量达到千万级别,效率上会很慢。所以打算放弃这个选项,选择仿百度那样的分页方式。每个页面只提供最多10个选项的页面连接。类似以下这样
现在先说说如何分页显示,后台关键代码如下:
//仿百度页码显示
//page为当前的页码
//listBegin为分页左端的页码,也即离上一页最近的那个页码
//listEnd为分页右端的页码,也即离下一页最近的那个页码
//totalPage为总的页面数
listBegin = (page - (int) Math.ceil((double) 10 / 2));//从第几页开始显示分页信息
if (listBegin < 1) { //当前页-(总显示的页列表数/2)
listBegin = 1;
}
listEnd = listBegin+9;//分页信息显示到第几页//当前页+(总显示的页列表数/2)
if (listEnd > totalPage) {
listEnd = totalPage;
}
if(listEnd<=10){
listBegin = 1;
}else{
listBegin = listEnd - 9;
}
jsp页面上显示:
<div class="pagination">上面只是页面上的关键代码,其中的数据显示内容用struts2标签。这样一个防百度的简单分页样式就出来了。
<ul>
<s:if test="#request.page>1">
<li class="first-child">
<a href="javascript:void(0);" onclick="previous();return false;">上一页</a>
</li>
</s:if>
<s:iterator begin="%{listBegin}" end="%{listEnd}" var="pageNow" >
<s:if test="#pageNow==#request.page">
<li class="active"><span>${pageNow }</span></li>
</s:if>
<s:else>
<li><a href="javascript:void(0);" onclick="turn(this.id);return false;" id="${pageNow }">${pageNow }</a></li>
</s:else>
</s:iterator>
<s:if test="#request.page<#request.totalPage">
<li class="last-child">
<a href="javascript:void(0);" onclick="next();return false;">下一页</a>
</li>
</s:if>
</ul>
</div>
下面说说自己觉得自己可行的hbase分页方案。
在hbase中基于行健的检索速度是最快的,如果分页的时候还去全表搜索然后返回需要的那一页数据,那这样效率很慢。
hbase提供的new PageFilter()可以设定想要返回多少条数据。我们在分页的时候如果已经知道了那一页的首条记录的rowkey,这样我们以那个rowkey为起始取10条记录,这样的查询效率就很快了。现在的问题是如何每次分页查询的时候就已经获取到了该页的首条记录rowkey值。我的方案是这样的,在第一次查询的时候,先取根据查询条件获取到的前10条记录。然后基于第一次查询后,分页查询时如果点到10,表示要获取第10页的数据。在程序后端可以先根据查询条件获取前100条数据,也即第1页到第10页的数据,然后把1-10页每页的首条记录rowkey保存下来放到内存中。然后取第10页对应的rowkey,以这个rowkey为起点,根据 查询条件取10条记录,然后返回到界面。以此类推,这样如果再查第1页到第10页的数据 时,就可以很快的先从内存获取对应的rowkey,然后取10条记录。以此类推查10页以后的数据时以第10页的rowkey为起点重复类似以上的操作。这样在程序中每次获取的记录数最多也只是从第1页跳到第10页的100条数据。避免了全表搜索,本人用这种方案在400多万条数据量中分页取数据的效率基本在毫秒级别返回。只是不完善的一点是取数据总量比较费时,目前用hbase提供的协处理器取数据总量,400多万条数据需要耗时3-4秒,目前正在想有没有更好的方案。
文章写的不是很好,只是想写下来这几天想出来的这种方案。