【问题标题】:MongoDB 'count()' is very slow. How do we refine/work around with it?MongoDB 'count()' 非常慢。我们如何改进/解决它?
【发布时间】:2011-10-05 07:48:38
【问题描述】:

我目前正在使用具有数百万条数据记录的 MongoDB。我发现了一件很烦人的事情。

当我使用 'count()' 函数来收集少量的查询数据时,它非常快。但是,当查询的数据集合包含数千甚至数百万条数据记录时,整个系统变得非常缓慢。

我确保我已为必填字段编制索引。

有人遇到过同样的事情吗?您如何改善这一点?

【问题讨论】:

    标签: performance mongodb count


    【解决方案1】:

    除了创建正确的索引之外,现在还有另一种优化。

    db.users.ensureIndex({name:1});
    db.users.find({name:"Andrei"}).count();
    

    如果您需要一些计数器,我建议尽可能预先计算它们。通过使用原子$inc 操作而不使用count({})

    但是 mongodb 人在 mongodb 上努力工作,所以,count({}) 根据 jira bug,他们计划在 mongodb 2.1 中进行改进。

    【讨论】:

    • 感谢您的回答。但是,假设我想过滤掉数据记录并计算记录数。在这种情况下,$inc 对我没有多大帮助,不是吗?
    • @WinstonChen:这取决于您的过滤器。提供一个我会回答的例子。
    • 谢谢。假设我有数百万条这样的记录:{_id:"hash_code_here", bookname:"The Four Steps to the Epiphany", author:"Steven-Gary-Blank", category:10}。我有大约 100 万本书,其类别为 10,与类别 9、8、7 等相同。我的页面具有分页功能,可过滤并显示我的访问者所有类别为 10 或 9 的书籍,或8 或 7.... 类别应该是过滤器中的条件之一。访问者还可以添加“作者”标准或其他一些标准。我如何使用 $inc 来实现它?
    • 请注意,ensureIndex 自 3.0 起已弃用。请改用createIndex
    【解决方案2】:

    您可以确保在没有任何磁盘访问的情况下真正使用索引。

    假设您要计算名称为“Andrei”的记录

    您确保对名称进行索引(正如您所做的那样) 和

    db.users.find({name:"andrei"}, {_id:0, name:1}).count()
    

    您可以通过检查是否是最快的计数方式(预计算除外)

    db.users.find({name:"andrei"}, {_id:0, name:1}).explain() 
    

    显示设置为 true 的 index_only 字段。

    这个技巧将确保您的查询仅从内存(索引)而不是磁盘中检索记录。

    【讨论】:

    • 如果 MongoDB 决定它应该默认为index_only 之类的操作执行count,那么这对我来说听起来很像一个错误。跨度>
    • 在 2011 年确实如此,也许 jira.mongodb.org/browse/SERVER-1752 改变了这一点
    【解决方案3】:

    你现在很不走运,在 mongodb 中的计数很糟糕,并且在不久的将来不会变得更好。见:https://jira.mongodb.org/browse/SERVER-1752

    根据经验,您几乎不应该使用它,除非它是一次性的,很少发生的事情,或者您的数据库非常小。

    正如@Andrew Orsich 所说,尽可能使用计数器(计数器的缺点是全局写锁定,但无论如何都比 count() 好)。

    【讨论】:

      【解决方案4】:

      对我来说,解决方案是将索引更改为 sparse。 视具体情况而定,有条件就试试吧。

      db.Account.createIndex( { "date_checked_1": 1 }, { sparse: true } )
      
      db.Account.find({    
           "dateChecked" : { $exists : true }    
      }).count()
      

      318,000 条记录在集合中

      • 0.31 秒 - 稀疏索引
      • 0.79 秒 - 非稀疏索引

      【讨论】:

        【解决方案5】:

        根据最新版本的 mongodb 4.4 添加我的观察结果。我有0.80 TB 集合大小。

        我为我的收藏创​​建了一个索引 (UserObject.CountryID)。并运行此查询。

        db.users.aggregate([
        {
            $match : {
                "UserObject.CountryID" : 3
            }
        }]).group({_id: "Count", count: {$sum: 1}})
        

        总共花了

        • 06800 毫秒以获取大约 1300 万(1.3 千万)条记录,搜索 0.80 TB 集合大小。
        • 16274 毫秒以获取大约 3500 万(3.5 千万)条记录,搜索 0.80 TB 集合大小。
        • 41615 毫秒以获取大约 4200 万(4.2 千万)条记录,搜索 0.80 TB 集合大小。

        【讨论】:

          猜你喜欢
          • 2012-03-20
          • 1970-01-01
          • 2021-05-06
          • 2016-08-29
          • 2012-06-30
          • 1970-01-01
          • 1970-01-01
          • 2013-04-10
          • 2018-01-09
          相关资源
          最近更新 更多