投影使查询更慢

时间:2014-07-22 11:12:30

标签: mongodb mongodb-query

我在MongoDb中有超过600k的记录。 我的用户架构如下所示:

{
    "_id" : ObjectId,
    "password" : String,
    "email" : String,
    "location" : Object,
    "followers" : Array,
    "following" : Array,
    "dateCreated" : Number,
    "loginCount" : Number,
    "settings" : Object,
    "roles" : Array,
    "enabled" : Boolean,
    "name" : Object
}

以下查询:

db.users.find(
     {},
     { 
         name:1, 
         settings:1,
         email:1,
         location:1
     }
).skip(656784).limit(10).explain()

结果如下:

{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 10,
    "nscannedObjects" : 656794,
    "nscanned" : 656794,
    "nscannedObjectsAllPlans" : 656794,
    "nscannedAllPlans" : 656794,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 5131,
    "nChunkSkips" : 0,
    "millis" : 1106,
    "server" : "shreyance:27017",
    "filterSet" : false
}

并删除投影相同的查询db.users.find().skip(656784).limit(10).explain()

结果如下:

{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 10,
    "nscannedObjects" : 656794,
    "nscanned" : 656794,
    "nscannedObjectsAllPlans" : 656794,
    "nscannedAllPlans" : 656794,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 5131,
    "nChunkSkips" : 0,
    "millis" : 209,
    "server" : "shreyance:27017",
    "filterSet" : false
}

据我所知,投影总是会提高查询的性能。所以我无法理解为什么MongoDB的表现如此。有人可以解释一下吗。什么时候使用投影,什么时候不投影。以及如何在MongoDB中实现投影。

2 个答案:

答案 0 :(得分:4)

你是正确的,投影使MongoDB 2.6.3中的跳过查询更慢。这与2.6查询计划程序跟踪为SERVER-13946的优化问题有关。

2.6查询规划器(在2.6.3中)是在投影分析之后添加SKIP(和LIMIT)阶段,因此投影被不必要地应用于在跳过此查询期间被抛出的结果。我在MongoDB 2.4.10中测试了类似的查询,nScannedObjects等于我的limit而不是skip + limit返回的结果数。

有几个因素会影响您的查询效果:

1)您尚未指定任何查询条件({}),因此此查询正在natural order进行集合扫描,而不是使用索引。

2)无法覆盖查询,因为没有投影。

3)您的skip值非常大,为656,784。

查询计划肯定有改进的余地,但我不希望这种大小的跳过值在正常使用中是合理的。例如,如果这是一个分页应用程序查询,每页50个结果,那么skip()值将相当于页码13,135。

答案 1 :(得分:2)

除非您的投影结果产生了“仅索引”查询,并且这意味着只有结果中“投影”的字段所有仅存在于索引中,那么您始终为查询引擎生成更多工作。

你必须考虑这个过程:

  1. 我如何匹配?在文档或索引?找到适当的主要或其他索引。

  2. 给定索引,扫描并查找内容。

  3. 现在我该返回什么?索引中的数据是全部吗?如果没有回到集合并提取文件。

  4. 这是基本过程。因此,除非其中一个阶段以任何方式“优化”,否则事情“需要更长时间”。

    您需要将此视为设计“服务器引擎”并了解需要采取的步骤。考虑到你的条件都不符合在指定步骤中产生“最佳”的任何条件,你需要学习接受它。

    您的“最佳”案例是投影字段是所选索引中的字段。但实际上,即使这样也有加载索引的开销。

    因此明智地选择,并了解您编写查询的内容的约束和内存要求。这就是“优化”的全部内容。

相关问题