11

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

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

对比

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

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

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

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

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

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

重要提示:我知道复合索引的顺序确实很重要,但如上所述,我对单键索引查询感到好奇。既然我们在这里,也对完全非索引查询的情况感兴趣。:)

替代解释:换一种说法,假设 100User秒(50 已存档,50 未存档),给定两种可能的内部 MongoDB 搜索策略:

  1. 首先过滤掉所有 50 个archived用户,然后搜索剩余 50 个first_name值为“Billy”的未归档用户
  2. 首先在所有 100 个User文档中搜索first_name值“Billy”,然后通过删除任何已归档的 Billys 来过滤找到的对象。

..我会假设#1更快(在具有两个以上条件的大型查询中可能更快)。但不管哪个更快,为什么,其中之一肯定是。

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

4

1 回答 1

18

我对您的问题感到有些困惑,仅仅是因为您提供的索引 ( { 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 会进行查询优化,以确定使用哪个索引最有效。您可以在此处阅读有关 MongoDB 执行的查询优化的更多信息。

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

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

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

.explain()您可以使用Mongo shell 中的功能查看查询正在使用哪个索引。(如果没有使用索引,您将"cursor" : "BasicCursor"在结果文档中看到。另一方面,如果正在使用复合索引,您会看到类似的"cursor" : "BtreeCursor first_name_1_archived_1"内容。如果使用了其中一个单字段索引,您可能会看到"cursor" : "BtreeCursor archived_1".

此外,MongoDB 的搜索策略是这样工作的:

  • 首先,遍历索引,使用索引边界过滤出尽可能多的文档;
  • 接下来,如果存在无法使用索引满足的附加谓词,
    • 获取文档,
    • 应用谓词,
    • 并适当地从结果中包含/排除文档。

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

tl;博士?Matcher 足够聪明,可以在相等谓词以任何顺序出现时匹配它们。

那有意义吗?

于 2013-09-19T18:32:46.370 回答