MongoDB海量数据分页查询优化
一、背景
大量数据需从Mongo拿出来,一次性拿出来不科学,传统分页效率低下
二、传统方案
就是最常规的方案,假设 我们需要对文章 articles 这个表(集合) 进行分页展示,一般前端会需要传递两个参数:
– 页码(当前是第几页)
– 页大小(每页展示的数据个数)
skip 跳过的条目也会随之变大,而这个操作是通过 cursor 的迭代器来实现的,对于cpu的消耗会比较明显。
而当需要查询的数据达到千万级及以上时,会发现响应时间非常的长,可能会让你几乎无法接受!
或许,假如你的机器性能很差,在数十万、百万数据量时已经会出现瓶颈
三、改良做法
既然传统的分页方案会产生 skip 大量数据的问题,那么能否避免呢?答案是可以的。
改良的做法为:
- 选取一个唯一有序的关键字段,比如 _id,作为翻页的排序字段;
- 每次翻页时以当前页的最后一条数据_id值作为起点,将此并入查询条件中。
四、性能测试
以10万条数据为例
总页数 | 传统翻页耗时(秒) | ID翻页耗时(秒) |
---|---|---|
100 | 0.18 | 0.09 |
500 | 3.01 | 0.33 |
1000 | 11.12 | 0.89 |
3000 | 93.58 | 2.60 |
可见,当页数越大(数据量越大)时,改良的翻页效果提升越明显!
这种分页方案其实采用的就是时间轴(TImeLine)的模式,实际应用场景也非常的广
而同时除了上述的数据库之外,HBase、ElastiSearch 在Range Query的实现上也支持这种模式。
五、完美分页
时间轴(TimeLine)的模式通常是做成“加载更多”、上下翻页这样的形式,但无法自由的选择某个页码。
那么为了实现页码分页,同时也避免传统方案带来的 skip 性能问题,我们可以采取一种折中的方案。