我对一个集合有多个索引,如下所示。特别是我想要一个查询使用"gTs_1_RE_H_1_l_1",但是查询使用的是"gTs_1"!
{
"0" : {
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "week_raw_tweet_db.tweets",
"name" : "_id_"
},
"1" : {
"v" : 1,
"key" : {
"gTs" : 1
},
"ns" : "week_raw_tweet_db.tweets",
"name" : "gTs_1",
"expireAfterSeconds" : 604800
},
"2" : {
"v" : 1,
"key" : {
"uN" : 1
},
"ns" : "week_raw_tweet_db.tweets",
"name" : "uN_1"
},
"3" : {
"v" : 1,
"key" : {
"gTs" : 1,
"RE_H" : 1,
"l" : 1
},
"ns" : "week_raw_tweet_db.tweets",
"name" : "gTs_1_RE_H_1_l_1",
"background" : 1
}
}这里我有一个关于'gTs‘的索引(基于TTL的索引)和一个以'gTs’和'RE_H‘作为前两个键的复合索引。("gTs_1_RE_H_1_l_1")
现在,我正在尝试执行以下查询:
db.tweets.find( {
"RE_H" : NumberLong("484001755192636620"),
"gTs" : {
"$lte" : ISODate("2014-03-18T22:00:00Z"),
"$gte" : ISODate("2014-03-17T21:00:00Z")
}
}).explain()据我所知,这应该使用"gTs_1_RE_H_1_l_1",但令人惊讶的是,它使用的是输出中提到的"gTs_1":
{
"cursor" : "BtreeCursor gTs_1",
"isMultiKey" : false,
"n" : 46508,
"nscannedObjects" : 365746,
"nscanned" : 365746,
"nscannedObjectsAllPlans" : 370493,
"nscannedAllPlans" : 370494,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 1509,
"indexBounds" : {
"gTs" : [
[
ISODate("2014-03-17T21:00:00.000Z"),
ISODate("2014-03-18T22:00:00.000Z")
]
]
},
"server" : "Frrole-API1:27017"
}不管怎么说,如果我给出一个提示,它确实会选择正确的索引。因此,如果我运行以下查询:
db.tweets.find( {
"RE_H" : NumberLong("484001755192636620"),
"gTs" : {
"$lte" : ISODate("2014-03-18T22:00:00Z"),
"$gte" : ISODate("2014-03-17T21:00:00Z")
}
}).hint("gTs_1_RE_H_1_l_1").explain()我得到以下输出:
/* 0 */
{
"cursor" : "BtreeCursor gTs_1_RE_H_1_l_1",
"isMultiKey" : true,
"n" : 46508,
"nscannedObjects" : 233224,
"nscanned" : 233541,
"nscannedObjectsAllPlans" : 233224,
"nscannedAllPlans" : 233541,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 3,
"nChunkSkips" : 0,
"millis" : 1874,
"indexBounds" : {
"gTs" : [
[
true,
ISODate("2014-03-18T22:00:00.000Z")
]
],
"RE_H" : [
[
NumberLong(484001755192636620),
NumberLong(484001755192636620)
]
],
"l" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "Frrole-API1:27017"
}有人能帮我理解一下发生了什么事吗!
发布于 2014-03-19 09:53:54
从输出中可以看到,使用简单索引的查询速度大约为300‘s,这就是mongodb使用该索引的原因。MongoDB的优化并不试图理解查询路径并猜测它的速度,它只是执行不同的查询和度量,其中一个是最快的。您的MongoDB已经了解到使用简单的gTs索引更快。它将通过并行运行不同的查询来不时地自动测试这一点。
据我所知,这应该使用"gTs_1_RE_H_1_l_1",但令人惊讶的是,它使用的是输出中提到的"gTs_1“:
这并不令人惊讶。您应该查看有关索引的文档,特别是关于排序的章节。虽然这里不请求排序,但使用的是range查询($lte及其兄弟姐妹),这非常类似。您至少需要将索引的顺序更改为RE_H,gTs,以便首先为equals约束创建索引,然后是范围查询。
发布于 2022-05-08 07:02:00
在选择索引时,定义索引的顺序似乎也很有效,例如:
{
"0" : {
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "week_raw_tweet_db.tweets",
"name" : "_id_"
},
"1" : {
"v" : 1,
"key" : {
"gTs" : 1,
"RE_H" : 1,
"l" : 1
},
"ns" : "week_raw_tweet_db.tweets",
"name" : "gTs_1_RE_H_1_l_1",
"background" : 1
},
"2" : {
"v" : 1,
"key" : {
"gTs" : 1
},
"ns" : "week_raw_tweet_db.tweets",
"name" : "gTs_1",
"expireAfterSeconds" : 604800
},
"3" : {
"v" : 1,
"key" : {
"uN" : 1
},
"ns" : "week_raw_tweet_db.tweets",
"name" : "uN_1"
}
}https://stackoverflow.com/questions/22499148
复制相似问题