Mongo更新不使用正确的索引

时间:2016-11-09 21:16:18

标签: mongodb indexing profiling

我正在尝试调试慢速查询。我的索引设置如下:

db.myCollection.getIndices()
...
{
  "key" : {
    "field1" : 1,
    "field2" : 1
  },
  "background" : true
}
...

这是一个超慢的查询:

{
  "op" : "update",
  "query" : {
    "field1" : "some_f1_value",
    "field2" : {
      "$exists" : 1
    }
  },
  "millis" : 59302,
  "ts" : ISODate("2016-11-09T19:43:41.754Z")
}

运行explain(),我得到以下内容:

db.myCollection.find({ "field1" : "some_f1_value", "field2" : { "$exists" : 1 } }).explain()

    "parsedQuery" : {
      "$and" : [
        {
          "field1" : {
            "$eq" : "some_f1_value"
          }
        },
        {
          "field2" : {
            "$exists" : true
          }
        }
      ]
    },
    "winningPlan" : {
      "stage" : "KEEP_MUTATIONS",
      "inputStage" : {
        "stage" : "FETCH",
        "filter" : {
          "field2" : {
            "$exists" : true
          }
        },
        "inputStage" : {
          "stage" : "IXSCAN",
          "keyPattern" : {
            "field1" : 1
          },
          "indexName" : "field1_1",
          "isMultiKey" : false,
          "direction" : "forward",
          "indexBounds" : {
            "field1" : [
              "[\"some_f1_value\", \"some_f1_value\"]"
            ]
          }
        }
      }
    }

似乎它没有同时使用field1field2上的索引,而是仅使用field1上的另一个索引,然后进行扫描以找到匹配的{{1} }。有没有解释,这可能是查询缓慢的原因吗?

编辑:好的,非常有趣。我测试了三个查询:

1)field2 - 这很慢,如上所述,只使用field1索引

2)db.myCollection.find({ "field1" : "val1", "field2":{$exists:1}}).explain() - 这很快,并正确使用field1 + field2 index

3)db.myCollection.find({ "field1" : "val1", "field2":{$exists:1}}).hint({field1:1, field2:1}).explain() - 这也很快,并正确使用field1 + field2索引

我应该澄清“val1”对于每个查询实际上是不同的(以便不使用mongo使用的OS缓存)但每个查询返回大约相同数量的文档。

所以似乎Mongo不使用db.myCollection.find({ "field1" : "val1", "field2":"val2"}).explain()查询的索引。这里有一些讨论:

Can MongoDB use an index when checking for existence of a field with $exists operator?

似乎人们认为这是固定的2.4。似乎并非如此,因为我正在使用3.0.6。

0 个答案:

没有答案