MST

星途 面试题库

面试题:MongoDB复杂查询场景下的索引设计与性能调优案例

假设你正在处理一个社交媒体应用的MongoDB数据库,其中一个集合存储了用户发布的帖子信息,包括用户ID、帖子内容、发布时间、点赞数、评论数等字段。现在有如下复杂查询需求:1. 查询点赞数大于100且评论数大于50的最近一周内发布的帖子;2. 查询某个用户发布的点赞数排名前10的帖子。请详细说明针对这两个查询需求,如何设计索引以达到最优性能,并解释设计思路及可能遇到的索引覆盖、索引冲突等问题,同时给出索引创建语句。
40.3万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

第一个查询需求:查询点赞数大于100且评论数大于50的最近一周内发布的帖子

  1. 索引设计思路
    • 这个查询涉及点赞数、评论数和发布时间三个字段。为了达到最优性能,我们应该创建一个复合索引,将查询条件中的字段按查询条件的选择性从高到低排列。一般来说,点赞数和评论数的选择性相对较高,而时间范围(最近一周)相对较宽泛。所以索引顺序为点赞数、评论数、发布时间。
  2. 可能遇到的问题
    • 索引覆盖:如果查询返回的字段都包含在索引中,那么可以使用索引覆盖,直接从索引中获取数据,而不需要回表操作,从而提高查询性能。例如,如果只查询帖子ID、点赞数、评论数和发布时间,这个索引就可以实现索引覆盖。
    • 索引冲突:如果数据库中已经存在其他索引,新创建的索引字段顺序与已有索引冲突,可能会导致索引维护成本增加。例如已有索引是(发布时间,点赞数),而新创建的索引为(点赞数,评论数,发布时间),虽然字段有重合,但顺序不同,可能会在某些操作(如插入、更新)时增加额外的索引更新开销。
  3. 索引创建语句
db.posts.createIndex({likes: 1, comments: 1, publishTime: 1});

这里likes表示点赞数,comments表示评论数,publishTime表示发布时间,1表示升序排列(如果是 -1 则表示降序排列)。

第二个查询需求:查询某个用户发布的点赞数排名前10的帖子

  1. 索引设计思路
    • 此查询涉及用户ID和点赞数两个字段。创建一个复合索引,将用户ID放在前面,因为要先定位到特定用户,然后再根据点赞数进行排序。所以索引为(用户ID,点赞数)。
  2. 可能遇到的问题
    • 索引覆盖:如果查询返回的字段都包含在索引中,例如只查询帖子ID、用户ID和点赞数,那么可以利用索引覆盖,避免回表操作,提升查询效率。
    • 索引冲突:如果已有索引包含用户ID或者点赞数且顺序不同,可能会产生索引冲突。比如已有索引是(点赞数,用户ID),新创建(用户ID,点赞数),在数据操作时可能会增加索引维护成本。
  3. 索引创建语句
db.posts.createIndex({userId: 1, likes: -1});

这里userId表示用户ID,likes表示点赞数,-1表示点赞数以降序排列,这样可以直接获取点赞数排名前10的帖子。