【问题标题】:Index for queries with $ne and $or with arrays带有 $ne 和 $or 数组的查询的索引
【发布时间】:2017-02-16 15:13:15
【问题描述】:

假设我有一个包含如下文档的 MongoDB 集合:

{ "_id": ObjectId("the_object_id"),
  "type": "BLOG_POST",
  "state": "IN_PROGRESS",
  "createDate":ISODate("2017-02-15T01:01:01.000Z"),
  "users": {
      "posted": ["user1", "user2", "user3"],
      "favorited": ["user1", "user4", "user5", "user6"],
      "other_fields": "other data",
   },
   "many_more_fields": "a bunch of other data"
}

我有一个这样的查询:

db.collection.find({"$and":[
    {"type": "BLOG_POST"},
    {"$or": [ {"users.posted":"userX"}, {"users.favorited":"userX"} ] },
    {"state": {"$ne":"COMPLETED"}}
]}).sort({"createDate":1})

该集合目前仅在 _id 字段上具有索引,并且某些字段未包含在此查询或示例中。

就基数而言,文档包含: type=BLOG_POST 大约是集合的 75%,状态 $ne "COMPLETED" 大约是集合的 50%,用户在 users.posted 或 users.favorited 中最多占集合的 2%。

对于这个用例,最好的索引或索引集是什么?

据我了解,我们不能在同一个索引中同时索引 users.posted 和 users.favorited,因为它们都是数组。将来我们可能会创建一个新的 users.userswhocare 数组,它是两个字段的集合,但假设我们不能在短期内做出改变。

我还认为 state 上的 $ne 意味着通常不会使用 state 上的索引。查询规划器是否能够通过索引末尾的 state 字段来处理 $ne 条件?

我有一个索引 {"type":1, "createDate":1, "state":1} 的想法,以便查询会命中类型,使用 createDate 进行排序,并处理$ne 与索引的最后一位。它仍然需要提取 35%-40% 的文档来为用户进行测试。不好,但比当前的集合扫描有所改进。

或者,我可以创建两个索引,一个像 {"users.posted":1, "type":1, "createDate":1, "state":1} 和 {"users.favorited":1, "类型”:1,“创建日期”:1,“状态”:1}。 查询规划器是否会使用这两个索引的交集来更快地找到感兴趣的文档?

我们目前使用的是 MongoDB 3.2.5。如果 MongoDB 3.2 和 3.4 之间的答案存在差异,我很想知道它们。

【问题讨论】:

    标签: mongodb mongodb-query mongodb-indexes


    【解决方案1】:

    经过一些分析,我发现在各个索引中添加多个以users.postedusers.favorited 作为第一项的查询都表现得更好,并且被 MongoDB 查询计划器选择。

    我创建了如下索引:

    db.collection.createIndex({"users.posted":1, "type":1, "createDate":1, "state":1})
    db.collection.createIndex({"users.favorited":1, "type":1, "createDate":1, "state":1})
    

    由于 users.posted 和 users.favorited 的基数很高(其中一个包含不超过集合的 2%,大多数时候小于 0.5%),MongoDB 查询计划器同时使用索引交集.

    我根据如下索引对此进行了测试:

    db.collection.createIndex({"type":1, "createDate":1, "state":1}).  
    

    查看使用 explain()explain("executionStats") 的两个查询的解释计划,查询计划程序使用索引扫描 {"$or": [ {"users.posted":"userX"}, {" users.favorited":"userX"} ] } 部分查询作为第一阶段。这导致 totalKeysExamined 和 totalDocsExamined 最少。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多