2

MongoDB 开发人员提示和技巧中的提示#25是否正确?

它说这个查询:

collection.find({"x" : criteria, "y" : criteria, "z" : criteria})

可以优化

collection.ensureIndex({"y" : 1, "z" : 1, "x" : 1})

我认为这是错误的,因为要使它起作用, x 应该在前面。我认为索引的顺序很重要。

那么我哪里做错了?

4

3 回答 3

5

仅当查询不包括索引中的所有字段时,索引中字段的顺序才重要。此查询引用所有三个字段,因此索引中字段的顺序无关紧要。

在有关复合索引的文档中查看更多详细信息。

查询对象中字段的顺序find不相关。

于 2013-01-15T01:57:13.677 回答
1
  • 对于想要更好地理解它的初学者
  • Mongodb 说索引包含对文档的引用,这些文档首先按 item 字段的值排序,在 item 字段的每个值中,按 stock 字段的值排序。”这是什么意思????
  • 让我们按升序在字段 a、b、c 和 d 上创建复合索引 (1)
Model.createIndex({ a: 1, b: 1, c: 1, d: 1 });
  • 我将其想象为:

    • 在第 1 级,根据第一个索引字段 (a) 的值按指定顺序 (1) 排序的参考列表
    • 在第 2 级,第 1 级的每个引用根据链 (b) 中第二个字段的值以指定的顺序 (1) 保存来自其位置的另一组引用。
    • 在第 3 层,第 2 层的每个引用根据链 (c) 中第二个字段的值以指定的顺序 (1) 保存来自其位置的另一组引用。
    • 在第 4 级,第 3 级的每个引用根据链 (d) 中第二个字段的值以指定的顺序 (1) 保存来自其位置的另一组引用。
  • 该链形成一个树结构,因此被选择存储在B-TREE data structure.

  • 在这种情况下,我很想将此存储系统称为 a compound-index-chain

  • 通常我们建立索引来执行两种类型的操作1. Query Operation like find()2. Non-query operation like Sort()

  • 现在您在{ a: 1, b: 1, c: 1, d: 1 }. 但仅创建索引是不够的。如果您不以使用这些索引的方式构建数据库操作(查找和排序),它就会变得低效甚至无用。

  • 让我们深入挖掘一下什么样的查询支持什么样的索引?

  • 寻找():

    • 以下prefixes复合索引还支持find()对字段的索引查询操作
    {a:1},
    {a:1, b:1},
    {a:1, b:1, c:1}
    // Index prefixes are the beginning subsets of indexed fields
    
    • @JohnnyHK 已经说过“查找查询对象中字段的顺序不相关。”

      • 这些字段可以是任何顺序,例如 {b:1, a1} 而不是 {a1:, b:1}。只要在复合索引或复合索引的前缀上操作 find() 操作,仍将使用索引。
      • 但是,performance即使 find() 查询使用相同的索引并且正在使用索引,如果 find() 中的字段顺序与其他后续字段相比不具有高度选择性,则查询的结果将不一样(可能会降级) 。
      • 意思是,如果查询中的第一个字段说find({a: 'red', b: tshrt})has ,那么即使两个查询都使用一个 index HIGH SELECTIVITY,查询的效率也会低于find({a: 'tshirt', b: 'red'})这个查询 hs 。LOWER SELECTIVITY{a:1, b:1}
      • 然而,HIGHLY SELECTIVE 查询将比根本没有任何索引执行得更好。
      • 我认为@Sushil 试图触及这个话题。
        • 如果您仍然想知道,Query selectivity是指查询谓词排除或过滤出集合中的文档的程度。查询选择性可以决定查询是否可以有效地使用索引,甚至可以完全使用索引。
    • 现在让我们来看看复合索引的前缀

    • 注意:find()复合索引 {a:1, b:1, c:1, d1} 的这个 {a:1, c:1} 前缀的行为与其其他前缀不同吗?

    • 在这种情况下,find()操作将无法有效地利用我们的复合索引。

    • 发生的事情是a:1 field索引将只能支持查找查询。index onc:1 field根本不会被使用,因为由于前缀compound-index-chain中没有,所以在两者之间被打破了。b:1 index field

    • 因此,如果 find() 查询同时对 a 和 c 字段进行操作,则将field a:1使用 IXSCAN(即在 a 上使用索引)和field cCOLLSCAN(即不使用索引)。意味着查询将比使用单独的复合索引要慢,{a:1,c:1}但比根本没有任何索引要快。

    • 结论是索引字段是按顺序解析的;如果查询省略了特定的索引前缀,则无法使用该前缀后面的任何索引字段。

  • 2.排序():

    • 对于non-query-operation(i.e Sort),在创建复合索引时,复合索引的子集必须相同order of the index,也必须位于same or oposite direction为每个字段指定的方向之一。

    • 让我们看看{ a: 1, b: 1, c: 1, d: 1 }带有升序方向的复合索引在 sort() 操作中的表现:

    • 让我们看一下索引字段在排序中的方向。

      • 正如我们所知,{a:1} 上的单个字段索引可以支持 {a:1} 同向和 {a:-1} 反向排序,
      • 复合索引在排序时遵循相同的规则。
      {a:1, b:1, c:1, d:1} // in same-direction as of our compound index
      {a:-1, b:-1, c:-1, d:-1 } // in reverse-direction of our compound index
      
      // But these field have neither same-direction nor reverse-direction but is ARBITARY/MIXED. Thus
      // Index will be discarded while performing sorting with these fields and directions
      {a:-1:, b:1, c:1, d:1}
      
      • 另一个例子是compound index on {a:1, b:-1}可以支持在 {a:1,b:-1} (same-direction) 和 {a:-1,b:1}(reverse-direction) BUT 上的索引排序NOT support {a:-1, b:-1}
    • 现在让我们看看索引字段在排序中的顺序

    • 最佳排序:

      • 当使用复合索引或使用复合索引的前缀进行排序操作时,不需要检查内存(RAM)中的结果集。这种排序操作仅满足索引中可用的字段,从而在排序操作中提供最佳性能。
      • 例如:
      // compound index
      {a:1, b:1, c:1, d:1}
      
      // prefix of the compound index
      {a:1},
      {a:1, b:1},
      {a:1, b:1, c:1}
      
      
    • 复合指数链断裂:

    • 当一个排序操作被复合索引部分覆盖时,可能需要检查内存中的非索引匹配结果集。

    Model.find({ a: 2 }).sort({ c: 1 }); // will not use index for sorting using field c. But will be used for finding
    Model.find({ a: { $gt: 2 } }).sort({ c: 1 }); // will not use index for sorting But will be used for finding
    // because compound-index-chain-break due to absence of field b of the prefix {a:1, b:1, c:1} of our compound index {a:1, b:1, c:1, d:1}
    
    • 按非前缀子集排序:

    • 当索引的前缀键同时出现在查询谓词(即 find())和 sort() 中时,位于排序子集之前(或重叠)的索引字段必须具有相等条件($eq,$gte,$lte ) 在查询中。所以

    • 复合索引也可以支持对其索引前缀的索引查询。

    Model.find({ c: 5 }).sort({ c: 1 }); // will not use index at all because it does not belongs to any of the prefix of our compound index
    Model.find({ b: 3, a: 4 }).sort({ c: 1 }); // will use the index for both finding and sorting as it belongs to one our index prexfix ie. {a:1, b:1, c:1}
    
    Model.find({ a: 4 }).sort({ a: 1, b: 1 }); // will use index for finding but not use index for sorting because a field is overlapped.
    Model.find({ a: { $gt: 4 } }).sort({ a: 1, b: 1 }); // will use index for both finding and sorting because overlapped field (a) in the predicate uses equality operator and it belongs to the prefix {a:1, b:1}
    
    Model.find({ a: 5, b: 3 }).sort({ b: 1 }); // will not use index for sorting
    Model.find({ a: 5, b: { $lt: 3 } }).sort({ b: 1 }); // will use index for both finding and sorting
    
  • 希望这可以帮助某人

于 2021-08-15T21:02:30.913 回答
0
于 2013-01-15T07:41:02.870 回答