提问者:小点点

在MongoDB中,我使用了一个大型查询,我将如何创建复合索引或单个索引,从而提高响应时间


在我的项目中,我有一个帖子集合,这是方案:

posts:{
        title:            {type: String, required: false},
        text:             {type: String, required: false},
        plainDescription: {type: String, required: false},
        isBlog:           {type: Boolean,default: false},
        type:             {type: String, required: true, default:'USER', enum:["USER","GROUP"]},
        information:{
            tags:[],
            users:[],
            groups:[],
            likes:[],
            likesCount:   {type: Number, default: 0},           
            dislikes:[],
            dislikesCount:{type: Number, default: 0},
            spams:[],
            spamsCount:   {type: Number, default: 0},
            shares:[],
            sharesCount:  {type: Number, default: 0},
            comments:[],
            commentsCount:{type: Number, default: 0},
            reply:[],
            favorite: [],
            favoriteCount:{type: Number, default: 0},
            replyCount:   {type: Number, default: 0}
        },
        authorId            : { type: String, required: true},// Can be user Id or Group Id
        authorName          : { type: String, required: false},
        isReply             : { type: Boolean, default: false},
        replyOf             : { type: String, default: "",nullable: true, references: 'posts._id'},
        isQuoteReyell       : { type: Boolean, default: false},
        quoteReyellOf       : { type: String, default: "",nullable: true, references: 'posts._id'},
        createdAt           : { type: Date, default: Date.now},
        createdBy           : { type: String, required: false, references: 'users._id'},
        creatorName         : { type: String, required: true, references: 'users.userName'},
        updatedAt           : { type: Date, required: false,default: Date.now},
        updatedBy           : { type: String, required: false, references: 'users._id'},
        updatorName         : { type: String, required: false, references: 'users.userName'},
        publishedAt         : { type: Date, required: false},
        isBlockedByAdmin    : {type:  Boolean,default: false},
        isDelete            : {type:  Boolean,default: false},
        isRss               : {type:  Boolean,default: false},
        updatedObj          : [],
        sportName           : {type: String, default: ''},
        teamObj             : []
    },

根据我的要求,这是一个查询:

[{"$match":{"$and":[{"$or":[{"$and":[{"createdBy":{"$in":["5754c557bd961f3751ddd830"]}},{"createdAt":{"$lt":"2017-10-26T06:17:32.533Z"}},{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"isQuoteReyell":{"$ne":true}},{"updatedObj":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"type":"reyell","updatedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}},{"isReply":false}]},{"$and":[{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"isReply":true},{"createdBy":{"$in":["5754c557bd961f3751ddd830"]}},{"updatedAt":{"$lt":"2017-10-26T06:17:32.533Z"}}]},{"$and":[{"updatedObj":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"type":{"$ne":"reyell"},"updatedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"createdBy":{"$in":["5754c557bd961f3751ddd830"]}},{"createdAt":{"$lt":"2017-10-26T06:17:32.533Z"}},{"isBlog":false},{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"isQuoteReyell":{"$ne":true}},{"updatedObj":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"type":"reyell","updatedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}},{"isReply":false}]},{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}},{"$and":[{"isReply":true},{"createdBy":{"$in":["5754c557bd961f3751ddd830"]}},{"updatedAt":{"$lt":"2017-10-26T06:17:32.533Z"}},{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]},{"$and":[{"information.shares":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"sharedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}},{"updatedObj":{"$elemMatch":{"userId":{"$in":["5754c557bd961f3751ddd830"]},"type":{"$ne":"reyell"},"updatedAt":{"$not":{"$gt":"2017-10-26T06:17:32.533Z"}}}}}]}]},{"isBlockedByAdmin":false},{"isDelete":false}]}},{"$unwind":"$updatedObj"},{"$match":{"$or":[{"$and":[{"updatedObj.type":"reyell"},{"updatedObj.userId":{"$in":["5754c557bd961f3751ddd830"]}}]},{"$and":[{"updatedObj.type":"create"}]}]}},{"$group":{"_id":"$_id","updated":{"$last":"$updatedObj"},"post":{"$last":"$$ROOT"}}},{"$sort":{"updated.updatedAt":-1}},{"$limit":15}]

请帮助我,对于哪一列,我应该创建一个索引或复合索引,这样可以加快响应时间。


共1个答案

匿名用户

通常,您希望在最重要/最频繁的查询中对最常用的字段设置一个索引,首先从选择最多的字段开始。在MongoDB文档中有一些关于这个主题的适当指导。其中对您的案例特别感兴趣的一个语句可能是这样的,因为您有很多

通常,MongoDB只使用一个索引来完成大多数查询。但是,OR查询的每个子句可能使用不同的索引,从2.6开始,MongoDB可以使用多个索引的交集。

然而,这里最重要的是使用explain()来测量,度量,度量和查看查询执行计划。原因是,您的应用程序很可能需要支持不同类型的查询,并且您需要在索引维护成本(例如,在索引更新期间写入锁&磁盘空间要求)和理论上最快的解决方案(即单个查询中使用的所有字段都由单个索引覆盖)之间进行权衡。

整个索引主题有点模糊,这在很大程度上取决于您的精确场景:

您将无法找到帮助所有查询执行最佳性能的单个索引。此外,当添加更多索引或更改现有索引时,这可能导致查询优化器停止对某些查询使用某些索引,而选择不同的执行计划,这可能是所需的,也可能不是所需的。因此,在索引或物理数据布局(硬件设置,分片。。。。)发生任何变化时,衡量所有重要的内容。最后,您应该随着数据量的增长定期测量查询性能,除非它的分布可以预测是一致的。

长话短说:采用迭代方法,首先添加一个索引(我建议在上添加一个索引),然后测量查询性能,然后根据发现改进索引(一次又一次,。。。)。