关于 MongoDB 索引优化的疑问

环境:mongodb 3.0.6
test结构大致如下:

{
    _id:                     ObjectId,
    contest: {
        _id:                 String,
        parentId:            String,
        type:                String,
        name:                String
    },
    contestant: {
        _id:                 String,
        name:                String,
        distraibutor: {
            _id:             String,
            type:            String,
            name:            String
        }
    },
    agent: {
        _id:                 String,
        type:                String,
        name:                String
    },
    score:                   Number,
    startTime:               Date,
    timeElapsed:             Number,
    status:                  String
}

对应查询语句如下:

db.test.aggregate(
    [
        { $match: {
            $and: [
                { $or: [
                    { 'contest.type': 'xxxxxx' },
                    { 'contest.type': null } 
                ] },
                { $or: [
                    { 'agent._id': 'xxxxxx' },
                    { 'contestant.distributor._id': { $in: [ 'xxxxx', 'xxxxx' ] } }
                ] }
            ],
            status: { $in: [ 'xxxxx', 'xxxxx' ] }
        } },
        { $sort: { score: -1, timeElapsed: 1 } },
        { $group: {
            _id: '$contestant._id',
            contest: { $first: '$contest' },
            contestant: { $first: '$contestant' },
            score: { $first: '$score' },
            count: { $sum: 1 }
        } },
        { $match: {
            count: { $gt: 0 },
            score: { $gte: 0, $lte: 999 }
        } },
        { $sort: {
            'contest.parentId': 1,
            'contest._id': 1,
            score: -1,
            timeElapsed: 1
        } }
    ]
)

通过 cursor.explain() 方法发现 不论我创建了什么索引,或者把索引都删除掉,查询选用的索引都是{score:-1,timeElapsed:1}

现在的问题就是表中一共才40W的数据,这个查询一次就要让人崩溃(大概1小时)。求大神指导应该怎么优化?

阅读 2.2k
1 个回答

已解决。
根据官方文档 的提示,试着在第一个$sort前加$limit

    ...
    { $limit: Number.MAX_SAFE_INTEGER },
    { $sort: { score: -1, timeElapsed: 1 } },
    ...

虽然感觉这里的$limit加的一点意义都没有,但就是这么神奇的解决了问题。
个人理解$sort前没有$limit的话是会先全表扫描进行排序,然后再进行查询操作;而前面添加了$limit则是先查询出结果然后再进行排序,进而执行后续的操作...

总之就是这么神奇...

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进