2017-03-06 37 views
2

我需要复合指数为我的收藏,但我不知道钥匙订购MongoDB的合成指数

我的项目:

{ 
    _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

领域的索引中的顺序应该是:

  1. 领域上,您会为精确值查询。
  2. 要排序的字段。
  3. 您将在其上查询一系列值的字段。

你的情况,那就是:

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

然而,在布尔字段指标往往不是非常有用,因为平均MongoDB中仍然需要访问你的文件的一半。所以,我劝你做到以下几点:

  1. 重复采集用于测试目的
  2. 创建索引,你想测试(即{"isActive": 1, "createdAt": -1, "till": -1, "location": "2dsphere" }
  3. 在蒙戈外壳创建变量

    VAR EXP = db.testCollection.explain( 'executionStats')

  4. 执行以下查询exp.find({'you query'})它将返回描述EXEC统计获奖计划

  5. 的ution分析像钥匙: “nReturned”, “totalKeysExamined”, “totalDocsExamined”
  6. 删除索引,创建新的(即{"createdAt": -1, "till": -1, "location": "2dsphere"}),执行exp.find({'you query'})比较的结果与前一
+0

谢谢,阿列克 我要创建一些测试......但一些言论: isActive在〜95%是真实的,但由于某些原因的统计数据我做一些额外的查询:'db.collection.find( {$和:[{isActive:true},{'till':{$ gte:new Date()}}]})'和'db.collection.find({$ and:[{isActive:true},{ 'till':{$ gte:new Date()}},{createdAt:{$ gte:today}}]})',无需排序和geo。 kyes订单是否一样? P.S.非常感谢来自敖德萨的基辅( - : – none

+0

))很好。对于'createdAt'字段用作过滤器的情况,索引顺序是相同的。但是,如果查询中没有“createdAt”字段(既不在过滤器中,也不在排序中),建议的索引将不会被使用,可能最好为'till'字段创建一个更多的索引。但请记住,额外的索引会降低写入和删除操作的性能 –

2

在蒙戈,很多事情取决于数据和访问模式。在您的收藏上创建索引时,有几件事情需要考虑 -

  1. 如何从应用程序访问数据。 (您已经知道主要查询,所以这部分几乎完成)
  2. 数据大小和基数和数据范围。
  3. 数据操作。(读取和写入的频率将以何种模式发生)
  4. 特定查询一次只能使用一个索引。
  5. 索引使用不是静态的。 Mongo不断改变启发式使用的索引,并试图以优化的方式进行。所以如果你在soem时间看到index1被使用,可能会发生mongo在输入一些/足够不同类型/基数的数据之后使用index2。

指数对于您的应用程序性能可能会更好,也更糟糕。在生产中使用它们之前,最好通过外壳/指南针进行测试。

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

上面一行在蒙戈外壳进入时给你解释的对象上的光标可进一步用来检查性能问题。

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

注意要点在上面的输出是

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

我们努力争取前三项中的最小值(executionTimeMillis,totalKeysExamined和totalDocsExamined),并且“阶段”是告诉发生了什么的一件重要事情。如果Stage是“COLLSCAN”,那么它表示它正在查找每个文档以完成查询,如果Stage是“SORT”,则表示它正在执行内存中的排序。两者都不好。

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

  1. 如果“直到”将不得不像一个月终止日期一固定值一个月期间输入的所有项目,然后它不是一个好主意有索引。即使在此索引之后,数据库也必须扫描许多文档。此外,由于它是月结束日期,因此该指数在一年内只有12个条目。
  2. 如果“till”是“createdAt”之后的固定值,那么两者都有索引是不好的。
  3. 索引“isActive”不好,因为它只能使用两个值。

因此,请尝试使用实际数据并执行以下指标,并确定哪些指数应该适合考虑时间,否。的文档。审查等

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

应用这两个指标收集和执行ex.find()。sort()其中ex是可解释的游标。然后,您需要分析两个输出并进行比较才能做出最佳决定。

+0

非常感谢这样一个真棒解释! – none