MongoDB分页处理方案

MongoDB的分页性能是广大使用者所诟病的大问题之一,在大数据量环境下,如果一次跳转的页数过多,如10W多页,可能用户要等上几十秒(瞎掰的数据),有兴趣的可以去看一下这篇文章Paging& Ranking With Large Offsets: MongoDB vs Redis vsPostgreSQL

看完了你是不是对MongoDB的性能很失望,对Redis充满了崇敬?

其实这种对比是完全不公平的。

首先,看一下Redis,研究NoSQL的多少会了解一些吧,这是一种完全的内存缓存的存储系统,他完全称不上是个数据库,为什么这么说呢,因为数据库最基本的一个特征——持久化Redis是没有的。Redis和Memcached一样,是一种将数据全部放在内存中用于缓存的存储系统,因此它的性能就是内存的性能。

而MongoDB,乃至其他一切数据库,都会将数据存入硬盘,虽然MongoDB也会将部分热数据放入内存,但是面对千万级甚至上亿的数据量,让内存放下所有热数据是不可能的,所以如果一个查询匹配的数据过多的话,可能大部分的性能瓶颈都在页面交换(从硬盘上读数据)上了。

最后,你可以测一下关系型数据库的性能,相信很难有哪个关系型数据库的分页性能比MongoDB还好。

当然,这不是为MongoDB开脱,我认为10gen应该找到一些办法来优化一下这种分页之后大偏移量的性能严重下降问题,虽然我还没想到。

 

数据库性能瓶颈分析

出现这一现象的原因,在于用户的这种查询需要数据库根据条件做一次筛选或排序,这是非常耗时间的,比如:

db.user.find({age:{$gt:20, $lt:30}}).sort({registdate:1,name:-1})

你如果在Google的用户数据中(据说是亿级)进行了这种查询,假设这些数据使用MongoDB(实际应该是BigTable)存储的,匹配了上亿的数据量,这个过程,MongoDB需要一个compound index,类似于{age:1, registdate:1, name:-1}这种,首先要根据age过滤出符合{age:{$gt:20,$lt:30}}的数据,然后根据两个条件{ registdate:1, name:-1}进行排序,这个排序很可能会与原来的索引顺序不同,因此MongoDB需要花时间来进行这种排序操作,更重要的是基于内存大小的限制,这种排序的结果不可能用于存储在内存中,甚至不会记录而是每次都排序一遍(这是很正常的),如果你查询的是前一百条的数据还好,MongoDB也许只需要排序数百条数据就能返回排序好的前一百。

举个例子,减小一下数据规模,如下图:

MongoDB分页处理方案(适用于一般数据库的分页方法)

MongoDB由两个Shard组成,user这个Collection有{age:1, registdate:1, name:-1}的索引,假设查询前三条数据,即

db.user.find({age:{$gt:20, $lt:30}}).sort({registdate:1,name:-1}).limit(

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值