MongoDB复合指数

时间:2017-03-06 10:46:22

标签: mongodb indexing

我的收藏需要复合索引,但我不确定按键顺序

我的项目:

 {
     _id,
     location: {
        type:       "Point",
        coordinates: [<lng>, <lat>]
     },
     isActive: true,
     till:  ISODate("2016-12-29T22:00:00.000Z"),
     createdAt : ISODate("2016-10-31T12:02:51.072Z"),

     ...

 }

我的主要问题是:

 db.collection.find({
    $and: [
        {
            isActive: true
        }, {
            'till': {
                $gte: new Date()
            }
        },
        {
            'location': { $geoWithin: { $box: [ [ SWLng,SWLat], [ NELng, NELat] ] }  }
        }

    ]
 }).sort({'createdAt': -1 })

在人类中,我需要地图中可见部分的所有活动项目,这些项目尚未过期,新添加 - 首先。

创建此索引是否正常:

  db.collection.createIndex( { "isActive": 1, "till": -1, "location": "2dsphere", "createdAt": -1 } )

对于磁盘使用情况,性能的最佳顺序是什么?或许我必须创建几个索引......

谢谢!

2 个答案:

答案 0 :(得分:3)

索引中字段的顺序应为:

  1. 您将在其中查询确切值的字段。
  2. 要对其进行排序的字段。
  3. 您将在其中查询一系列值的字段。
  4. 在你的情况下,它将是:

    db.collection.createIndex( { "isActive": 1, "createdAt": -1, "till": -1, "location": "2dsphere"  } )
    

    但是,布尔字段的索引通常不是很有用,因为平均而言MongoDB仍然需要访问一半的文档。所以我建议你做以下事情:

    1. 复制集合以进行测试
    2. 创建索引,您想要测试(即{"isActive": 1, "createdAt": -1, "till": -1, "location": "2dsphere" }
    3. 在mongo shell中创建变量:

      var exp = db.testCollection.explain(&#39; executionStats&#39;)

    4. 执行以下查询exp.find({'you query'})它将返回描述获胜计划执行情况的统计信息

    5. 分析如下的键:&#34; nReturned&#34;,&#34; totalKeysExamined&#34;,&#34; totalDocsExamined&#34;
    6. 删除索引,创建新索引(即{"createdAt": -1, "till": -1, "location": "2dsphere"}),执行exp.find({'you query'})将结果与前一个比较

答案 1 :(得分:2)

在Mongo中,很多东西都依赖于数据及其访问模式。在您的收藏集上创建索引时,很少有事情需要考虑 -

  1. 如何从应用程序访问数据。 (你已经知道了主要的查询,所以这部分差不多完成了)
  2. 数据大小,基数和数据范围。
  3. 对数据的操作。 (读取和写入的频率和发生方式)
  4. 特定查询一次只能使用一个索引。
  5. 索引使用不是静态的。 Mongo不断改变启发式使用的索引,并尝试以优化的方式进行。因此,如果你看到在soem时使用了index1,那么当输入一些/足够的不同类型/基数数据时,mongo可能会在一段时间后使用index2。
  6. 对于您的应用程序性能而言,指数可能会变得更好也更糟。在生产中使用它们之前,最好通过shell / compass进行测试。

    var ex = db.<collection>.explain("executionStats")
    

    在mongo shell中输入以上行时,会在可解释对象上显示光标,可以进一步用于检查性能问题。

    ex.find(<Your query>).sort(<sort predicate>)
    

    以上输出中的注意事项是

    • “executionTimeMillis”
    • “totalKeysExamined”
    • “totalDocsExamined”
    • “阶段”
    • “nReturned”

    我们努力争取前三项(executionTimeMillis,totalKeysExamined和totalDocsExamined)的最小值,而“阶段”是告诉正在发生的事情的一个重要事项。如果Stage是“COLLSCAN”,那么它意味着它正在寻找满足查询的每个文档,如果Stage是“SORT”则表示它正在进行内存中排序。两者都不好。

    来到您的查询,有几件事需要考虑 -

    1. 如果“until”将在一个月内输入所有项目的固定值,例如月末日期,那么在其上输入索引并不是一个好主意。即使在此索引之后,DB也必须扫描许多文档。此外,鉴于月末结束日期,该指数一年只有12个条目。
    2. 如果“till”是“createdAt”之后的固定值,那么在两者上都有索引是不好的。
    3. 索引“isActive”并不好,因为它只能有两个值。
    4. 因此,请尝试使用实际数据并执行以下索引,并确定哪个索引应该适合考虑时间,否。的文档。检查等。

      1. {"location": "2dsphere" , "createdAt": -1}
      2. {"till":1, "location": "2dsphere" , "createdAt": -1}
      

      在集合上应用两个索引并执行ex.find()。sort()其中ex是可解释的游标。然后你需要分析两个输出并进行比较以确定最佳结果。