MongoDB索引变量查询

时间:2016-04-19 11:11:02

标签: mongodb indexing

我有一组用户生成的帖子。它们包含以下字段

_id: String
groupId: String // id of the group this was posted in
authorId: String
tagIds: [String]
latestActivity: Date // updated whenever someone comments on this post
createdAt: Date
numberOfVotes: Number
...some more...

我的查询总是看起来像这样...

Posts.find({
  groupId: {$in: [...]},
  authorId: 'xyz', // only SOMETIMES included
  tagIds: {$in: [...]}, // only SOMETIMES included
}, {
  sort: {latestActivity/createdAt/numberOfVotes: +1/-1, _id: -1}
});

所以我总是在groupId上查询,但有时只添加tagIds或userIds。我也会切换出对其进行排序的字段。我最好的索引策略怎么样?

从目前为止我在SO上读到的内容,我可能会创建多个复合索引,并始终以{groupId:1,_id:-1}开头 - 因为它们包含在每个查询中,是好的前缀候选人。 现在,我猜测为每个可能的组合创建一个新的索引并不是一个好主意。因此,我应该保持这样,只有索引groupId和_id?

感谢。

1 个答案:

答案 0 :(得分:0)

你正朝着正确的方向前进。对于复合索引,您需要左侧最具选择性的索引和右侧的范围。 {groupId: 1, _id: -1}满足了这一点。

记住,当密钥在从左到右的查询中时,使用复合索引也很重要。因此,一个复合索引可以涵盖许多常见场景。例如,如果您的索引为{groupId: 1, authorId:1, tagIds: 1}且查询为Posts.find({groupId: {$in: [...]},authorId: 'xyz'}),则会使用该索引(即使tagIds不存在)。此外,Posts.find({groupId: {$in: [...]},tagIds: {$in: [...]}})将使用此索引(使用索引的第一个和第三个字段,因此如果Mongo找不到更具体的索引,则将使用此索引)。但是,Posts.find({authorId: 'xyz',tagIds: {$in: [...]}})不会使用索引,因为索引中的第一个字段缺失。

鉴于所有这些,我建议从{groupId: 1, authorId:1, tagIds: 1, _id: -1}开始。 groupId是查询中唯一的非可选字段,因此它位于可选字段之前的左侧。看起来authorId比tagId更具选择性,所以它应该在groupId之后的左边。你按_id排序,所以应该在右边。请务必以Analyze Query performance查询数据的不同方式。确保他们都选择了这个索引(否则你需要做更多的调整或者可能需要第二个复合索引)。然后,您可以创建其他索引并强制查询使用它来对性能进行一些a-b测试。