如何在mongodb中构造复合索引

Mon*_*key 4 mongodb

我需要一些关于在mongo中创建和排序索引的建议.

我有一个包含5个属性的帖子集:

帖子

  • 状态
  • 开始日期
  • 结束日期
  • lowerCaseTitle
  • 排序

几乎所有帖子都具有相同的状态1,只有少数帖子具有被拒绝的状态.我的所有查询都将过滤状态,开始和结束日期,并对sortOrder进行排序.我还将有一个查询在标题上进行正则表达式搜索.

我应该在{status:1,start:1,end:1,sort:1}上设置复合键吗?将字段放在复合索引中的顺序是否重要 - 我应该将状态放在复合索引中,因为它是最广泛的吗?在每个属性上做复合索引而不是单个索引是否更好?mongo只对任何给定的查询使用单个索引吗?

如果我正在对其进行正则表达式查询,那么对于lowerCaseTitle上的索引是否有任何提示?

示例查询是:

db.posts.find({status: {$gte:0}, start: {$lt: today}, end: {$gt: today}}).sort({sortOrder:1})

db.posts.find( {lowerCaseTitle: /japan/, status:{$gte:0}, start: {$lt: today}, end: {$gt: today}}).sort({sortOrder:1})
Run Code Online (Sandbox Code Playgroud)

Rem*_*iet 16

这是一篇文章中的很多问题;)让我按实际顺序浏览它们:

  • 每个查询最多只能使用一个索引(顶级$或子句等除外).这包括任何排序.
  • 由于上述原因,您肯定需要一个复合索引来解决您的问题而不是单独的每个字段索引.
  • 低基数字段(因此,数据集中具有非常少的唯一值的字段)通常不应该在索引中,因为它们的选择性非常有限.
  • 复合索引中字段的顺序,复合索引中每个字段的相对方向也是如此(例如"{name:1,age:-1}").在mongodb.org上有很多关于复合索引和索引字段方向的文档,所以我不会在这里重复所有内容.
  • 如果排序字段位于索引中,则排序将仅使用索引,并且直接位于用于选择结果集的最后一个字段之后的索引中的字段.在大多数情况下,这将是索引的最后一个字段.

因此,您根本不应该在索引中包含状态,因为一旦索引遍历消除了基于更高基数字段的绝大多数文档,它在大多数情况下最多会留下2-3个文档,而这些文档很难通过状态索引进行优化(特别是因为你提到这2-3个文件很可能具有相同的状态).

现在,最后一个音符这是你的情况相关的是,当你使用范围查询(和你),它会不会使用索引反正排序.您可以在测试查询后查看explain()的"scanAndOrder"值来检查这一点.如果该值存在且为true,则表示它将在内存中排序结果集(扫描和顺序),而不是直接使用索引.在您的具体情况下,这是无法避免的.

所以,你的索引应该是:

db.posts.ensureIndex({start:1, end:1})
Run Code Online (Sandbox Code Playgroud)

和您的查询(订单修正为清楚起见只,查询优化器将通过相同的执行路径运行原来的查询,但我更喜欢把索引字段,第一,按顺序):

db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})
Run Code Online (Sandbox Code Playgroud)