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

tob*_*pwn 5 mongoose mongodb

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

conditions = { archived: false, first_name: "Billy" };
Run Code Online (Sandbox Code Playgroud)

conditions = { first_name: "Billy", archived: false };
Run Code Online (Sandbox Code Playgroud)

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

User.find(conditions, function(err, users) { <some logic> });
Run Code Online (Sandbox Code Playgroud)

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

UserSchema.index( { first_name: 1, archived: 1} );
Run Code Online (Sandbox Code Playgroud)

..上述条件的顺序是否重要?

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

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

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

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

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

Ama*_*lia 12

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

conditions = { archived: false, first_name: "Billy" };
conditions = { first_name: "Billy", archived: false };
conditions = { first_name: "Billy" };
Run Code Online (Sandbox Code Playgroud)

现在,让我们假设我们有两个独立的索引,{ first_name: 1 }并且{ archived: 1 }.在这种情况下,MongoDB将进行查询优化以确定哪个索引的使用效率最高.您可以在此处阅读有关MongoDB执行的查询优化的更多信息.

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

conditions = { archived: false, first_name: "Billy" };
conditions = { first_name: "Billy", archived: false };
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

TL;博士?匹配器足够智能,可以在按任何顺序显示时匹配等式谓词.

那有意义吗?