Performance MongoDB远程分页

Performance MongoDB远程分页,performance,mongodb,pagination,Performance,Mongodb,Pagination,据说在有很多记录的MongoDB集合中使用skip()进行分页速度很慢,不推荐使用 可以使用范围分页(基于>\u id比较) db.items.find({_id: {$gt: ObjectId('4f4a3ba2751e88780b000000')}}); 它很适合显示上一页和下一页下一步按钮-但是当你想显示实际的页码1时,它不是很容易实现。。。5 6 7 ... 124-您需要预先计算每页从哪个“_id”开始 所以我有两个问题: 1) 我什么时候开始担心这个?当“记录太多”且skip()速

据说在有很多记录的MongoDB集合中使用skip()进行分页速度很慢,不推荐使用

可以使用范围分页(基于>\u id比较)

db.items.find({_id: {$gt: ObjectId('4f4a3ba2751e88780b000000')}});
它很适合显示上一页和下一页下一步按钮-但是当你想显示实际的页码1时,它不是很容易实现。。。5 6 7 ... 124-您需要预先计算每页从哪个“_id”开始

所以我有两个问题:

1) 我什么时候开始担心这个?当“记录太多”且skip()速度明显减慢时?1 000? 100万

2) 使用范围分页时,用实际页码显示链接的最佳方法是什么?

好问题

“多少就是太多?”-当然,这取决于您的数据大小和性能要求。一、 就个人而言,当我跳过超过500-1000条记录时会感到不舒服

实际答案取决于您的要求。以下是现代网站的功能(或者至少是其中的一些)

首先,导航栏如下所示:

1 2 3 ... 457
他们从总记录数和页面大小中得到最终的页码。让我们跳到第三页。这将涉及从第一条记录中跳过一些内容。当结果到达时,您知道第3页上第一条记录的id

1 2 3 4 5 ... 457
让我们再跳过一些,转到第5页

1 ... 3 4 5 6 7 ... 457
你明白了。在每个点上,您都可以看到第一个、最后一个和当前页面,以及当前页面的前后两个页面

询问
很难给出一般性的答案,因为这在很大程度上取决于您使用什么查询(或多个查询)来构造要显示的结果集。如果只使用索引就可以找到结果并按索引顺序显示,那么db.dataset.find().limit().skip()即使有大量的跳过也可以很好地执行。这可能是编写代码的最简单方法。但即使在这种情况下,如果您可以缓存页码并将其与索引值绑定,您也可以加快第二个和第三个想要查看第71页的人的速度


在一个非常动态的数据集中,当其他人在数据中分页时,文档将被添加和删除,这样的缓存很快就会过时,而limit and skip方法可能是唯一可靠的方法,可以提供良好的结果。

我最近在使用非唯一字段(例如“FirstName”)对请求进行分页时遇到了同样的问题。此查询的思想是能够在不使用skip()的情况下对非唯一字段实现分页

这里的主要问题是能够查询非唯一“FirstName”字段,因为会发生以下情况:

  • $gt:{“FirstName”:“Carlos”}->这将跳过名为“Carlos”的所有记录
  • $gte:{“FirstName”:“Carlos”}->将始终返回相同的数据集
  • 因此,我提出的解决方案是通过将目标搜索字段与辅助字段相结合,使查询的$match部分唯一,从而使其成为唯一的搜索

    升序:

    db.customers.aggregate([
        {$match: { $or: [ {$and: [{'FirstName': 'Carlos'}, {'_id': {$gt: ObjectId("some-object-id")}}]}, {'FirstName': {$gt: 'Carlos'}}]}},
        {$sort: {'FirstName': 1, '_id': 1}},
        {$limit: 10}
        ])
    
    db.customers.aggregate([
        {$match: { $or: [ {$and: [{'FirstName': 'Carlos'}, {'_id': {$gt: ObjectId("some-object-id")}}]}, {'FirstName': {$lt: 'Carlos'}}]}},
        {$sort: {'FirstName': -1, '_id': 1}},
        {$limit: 10}
        ])
    
    降序排列:

    db.customers.aggregate([
        {$match: { $or: [ {$and: [{'FirstName': 'Carlos'}, {'_id': {$gt: ObjectId("some-object-id")}}]}, {'FirstName': {$gt: 'Carlos'}}]}},
        {$sort: {'FirstName': 1, '_id': 1}},
        {$limit: 10}
        ])
    
    db.customers.aggregate([
        {$match: { $or: [ {$and: [{'FirstName': 'Carlos'}, {'_id': {$gt: ObjectId("some-object-id")}}]}, {'FirstName': {$lt: 'Carlos'}}]}},
        {$sort: {'FirstName': -1, '_id': 1}},
        {$limit: 10}
        ])
    
    此查询的$match部分基本上是一个if语句: 如果firstName是“Carlos”,那么它也需要大于这个id 如果firstName不等于“Carlos”,则需要大于“Carlos”


    唯一的问题是,您无法导航到特定的页码(可能需要一些代码操作),但除此之外,它解决了我的非唯一字段分页问题,而不必使用skip,当到达您要查询的任何数据集的末尾时,skip会消耗大量内存和处理能力。

    谢谢,这正是我需要的。很好的组合aproach-range by“_id”+skip(),非常容易使用,比我今天在搜索主题时读到的所有aproach都要好。答案很好,但在这种方法中,你必须知道当前页码。知道它的唯一方法是将它发送到请求中,若索引需要反转,这个方法是否有效?排序({u id:-1})和另外一个问题:如何有效地获取最后一页?澄清-如果存在重复值,这将不起作用。如果其他人偶然发现了这一点,我会设法克服这一限制,按照自己的需要进行调整。