mongDB 分页优化

具体到这次调优,是一个关于mongoDB的分页问题。在分页时如果用skip,在页数比较大时,性能下降得非常厉害。

具体语句是db.foo.find().sort().skip().limit();mongo官方也明确说不建议用skip做分页。

做分页的标准做法是,记住上一个页的最后一个值,然后取这个值之后的100条记录,这样回避skip。具体语句如下:

 

var latest = null;

//显示第一页

while(page1.hasNext()) {

latest = page1.next();  //记住当前对象,在循环结束时,这个对象就是这页的最后一个对象

display(latest);     //送到前台展示

// 获取下一页,假设表名是foo,按date进行排序,$gt是大于的意思

var page2 = db.foo.find({"date":{"$gt":latest.date}});  //取时间大于latest.date的数据

page2.sort({"date":-1}).limit(100);  //在游标page2中取头100行记录。

 

这样就避免使用skip了。这是标准做法。

 

但即使这样的做法,数据量特别大时,性能也不好,尤其是用户直接点取最后一页时。

我建议在最后几页时,采用和取头几页相反的顺序。例如正常取评论时,是按时间逆序的,如果用户要看最后一页,就按时间正序取数据就好了,当然具体到产品,还有一些条件分支什么的,这些是宝龙自己细化的。

这种与正常逆序的取法,实际不是我自己想出来的,网上有一篇关于mongo调优的博文,最后一段提到了这种做法。

很好的一篇文章。



案例

 

//统计img
    public List<VideoEncode> doStaticImg() {
        List<VideoEncode> list = new ArrayList<VideoEncode>();
        int pageSize = 100;
        long count = videoEncodeDao.getCount(startTime, endTime);
        long pageCount = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
        long createTime = startTime;
        for (int i = 0; i < pageCount; i++) {
            List<VideoEncode> videoEncodeList = videoEncodeDao.getAll(createTime, endTime, pageSize);
            if (videoEncodeList.isEmpty()) break;
            createTime = videoEncodeList.get(videoEncodeList.size()-1).getCreateTime();
            List<VideoEncode> imgFailList = getImgPathFail(videoEncodeList);
            if (!imgFailList.isEmpty())  list.addAll(imgFailList);
        }
        return list;
    }
//获取指定时间转码、分发,checksum完成的任务
    public List<VideoEncode> getAll(long startTime, long endTime,int count){
        Query <VideoEncode> query=createQuery();
        query.field("status").equal(VideoEncode.STATUS_COMPLETE).field("videoCDNStatus").equal(VideoEncode.CDN_STAUTS_COMPLETE);
        query.field("checksumStatus").equal(VideoEncode.CDN_STAUTS_COMPLETE).field("mmsStatus").equal(VideoEncode.MMS_STATUS_SYNCED);
        query.field("vtype").equal("1").field("createTime").greaterThan(startTime).field("createTime").lessThan(endTime).order("encodeId");
        query.limit(count);
        QueryResults <VideoEncode> queryResults=find(query);
        return  queryResults.asList();
    }
//获取指定时间转码、分发,checksum完成的任务数量
      public long getCount(long startTime, long endTime){
        Query <VideoEncode> query=createQuery();
        query.field("status").equal(VideoEncode.STATUS_COMPLETE).field("videoCDNStatus").equal(VideoEncode.CDN_STAUTS_COMPLETE);
        query.field("checksumStatus").equal(VideoEncode.CDN_STAUTS_COMPLETE).field("mmsStatus").equal(VideoEncode.MMS_STATUS_SYNCED);
        query.field("vtype").equal("1").field("createTime").greaterThan(startTime).field("createTime").lessThan(endTime);
        return  count(query);

    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值