MongoDB(和Mongoose.js):查询条件的顺序是否重要?

时间:2013-08-12 04:18:22

标签: mongodb mongoose

在创建简单的MongoDB查询时,我对查询中的条件排序有疑问 - 例如(Mongoose.js语法):

conditions = { archived: false, first_name: "Billy" };

VS

conditions = { first_name: "Billy", archived: false };

..在一个简单的find()函数中:

User.find(conditions, function(err, users) { <some logic> });

..假设一个简单的单键索引策略:

UserSchema.index( { first_name: 1, archived: 1} );

..上面列出的条件的顺序是否重要?

重要提示:我知道复合索引的顺序很重要,但是上面我对单键索引查询感到好奇。也对完全非索引查询的情况感兴趣,因为我们在这里。 :)

替代解释:换句话说,假设有两个可能的内部MongoDB搜索策略,假设有100 User个(50个存档,50个没有):

  1. 首先过滤掉所有50个archived用户,然后搜索其余50个未归档的用户,其first_name值为“Billy”
  2. 首先在所有100个User文档中搜索first_name值“Billy”,然后通过删除已归档的任何Billy来过滤找到的对象。
  3. ..我认为#1更快(在具有两个以上条件的大型查询中可能更快)。但无论哪个更快,为什么,肯定其中一个是。

    核心问题:在复杂索引的庞大而强大的世界之外,MongoDB是否知道如何自动执行其最高性能/快速搜索/过滤器,无论哪个字段和哪个排序?或者我们是否需要以编程方式告诉系统什么是最好的(通过所提供条件的顺序等)?

1 个答案:

答案 0 :(得分:11)

我对您的问题感到有点困惑,因为您提供的索引({ first_name: 1, archived: 1 }复合索引。以下所有查询都将使用该复合索引:

conditions = { archived: false, first_name: "Billy" };
conditions = { first_name: "Billy", archived: false };
conditions = { first_name: "Billy" };

现在,我们假设我们有两个单独的索引,{ first_name: 1 }{ archived: 1 }。在这种情况下,MongoDB将进行查询优化以确定哪个索引的使用效率最高。 You can read more about the query optimization performed by MongoDB here.

因此,MongoDB查询优化器可能会对您提供的两个多路查询使用相同的索引:

conditions = { archived: false, first_name: "Billy" };
conditions = { first_name: "Billy", archived: false };

或者,您可以使用hint强制MongoDB使用您选择的索引。一般来说,这可能不是一个好主意。您还可以手动检查哪个索引对特定查询as detailed here最有效。

您可以使用Mongo shell中的.explain()功能查看查询使用的索引。 (如果没有使用索引,你会在结果文档中看到"cursor" : "BasicCursor"。另一方面,如果使用复合索引,你会看到像"cursor" : "BtreeCursor first_name_1_archived_1"这样的东西。如果其中一个使用了单字段索引,您可能会看到"cursor" : "BtreeCursor archived_1"

此外,MongoDB的搜索策略如下:

  • 首先,遍历索引,使用索引边界过滤掉尽可能多的文档;
  • 接下来,如果使用索引无法满足其他谓词,
    • 获取文档,
    • 应用谓词,
    • 并包含/排除来自结果的文件。

查询优化器并行运行所有可能的查询计划并选择“最佳”查询计划,但所有查询计划都遵循上述策略。 (BasicCursor是一个退化的案例:它遍历所有文档并将谓词应用于每个文档。)

tl; dr?匹配器非常智能,可以在按任意顺序显示时匹配等式谓词。

这有意义吗?