我正在尝试调试慢速查询。我的索引设置如下:
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\"]"
]
}
}
}
}
似乎它没有同时使用field1
和field2
上的索引,而是仅使用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。