如何强制 MongoDB 始终使用带有 $or 子句的特定索引

问题描述 投票:0回答:1

我有一个具有以下索引的 MongoDB 集合项:

db.items.createIndexes([{ team: 1, a: 1 }, { team: 1, b: 1 }])

我插入了一些这样的测试数据:

db.items.insertMany([
  { team: 1, a: "valueA1" },
  { team: 1, a: "valueA2" },
  { team: 1, a: "valueA3" },
]);

我有一个类似于以下内容的 MongoDB 查询:

db.items.find({
    team: [teamId],
    // dynamic query part
    $or: [{ a: [value] }, { b: [value] }]
})

我的目标是确保查询始终使用 team_1_a_1 和 team_1_b_1 索引,但实际索引选择会根据查询值和查询的动态部分而变化。

例如,当我运行以下查询时:

db.items.find({
    team: 1,
    $or: [{ a: "valueA1" }, { b: "valueB1" }]
}).explain("queryPlanner")

我得到了使用两个索引的预期结果:

"winningPlan": {
  "stage": "FETCH",
  "inputStage": {
    "stage": "OR",
    "inputStages": [
      {
        "indexName": "team_1_a_1",
        ...
      },
      {
        "indexName": "team_1_b_1",
        ...
      }
    ]
  }
}

但是,对于此查询:

db.items.find({
    team: 2,
    $or: [{ a: "valueA1" }, { b: "valueB1" }]
}).explain("queryPlanner")

结果与我的预期不符:

"winningPlan": {
  "stage": "FETCH",
  "inputStage": {
    "stage": "IXSCAN",
    "indexName": "team_1_a_1",
    ...
  }
}

我了解 MongoDB 有时会自动选择更好的索引。但在我的用例中,我有超过 1 亿个文档,索引选择存在性能问题,并且经常遇到以下错误:

multiplanner encountered a failure while selecting best plan :: caused by :: operation exceeded time limit

我正在寻找一种方法来强制 MongoDB 始终在 $or 子句中使用索引,类似于hint的工作方式,并跳过 MongoDB 的索引选择过程。关于如何实现这一目标有什么建议吗?

mongodb mongodb-query mongodb-indexes
1个回答
0
投票

你可以尝试改变索引键的顺序吗?

db.items.createIndexes([{ a: 1, team : 1 }, { b: 1, team: 1 }])

在这种情况下,因为两个索引都有前缀键:team,所以Mongo将进行自动选择过程。 如果我们反转键以在前缀处指定 $or 的过滤键,那么 mongo 将知道并选择正确的索引。

© www.soinside.com 2019 - 2024. All rights reserved.