今天我注意到,给出了$ lt和$ gt运算符的顺序似乎在MongoDB 2.0.2中很重要.
我有一个游戏数据库."player"是表示两个玩家的两个字符串的数组,"endedAtMS"是游戏结束时的时间戳.我创建了这个索引:
db.games.ensureIndex({player:1,endedAtMS:-1})
Run Code Online (Sandbox Code Playgroud)
为了获得30个在特定时间范围内完成的游戏,在游戏完成时排序,我这样做:
db.games.find({ "player" : "Stefan" ,
"endedAtMS" : { "$lt" : 1321284969946 ,
"$gt" : 1301284969946}}).
sort({endedAtMS:-1}).
limit(30).
explain()
{
"cursor" : "BtreeCursor player_1_endedAtMS_-1",
"nscanned" : 30,
"nscannedObjects" : 30,
"n" : 30,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"player" : [
[
"Stefan",
"Stefan"
]
],
"endedAtMS" : [
[
1321284969946,
-1.7976931348623157e+308
]
]
}
}
Run Code Online (Sandbox Code Playgroud)
一切似乎都很好.但是当我在上面的查询中更改$ lt和$ gt的顺序时,我得到了这个:
db.games.find({ "player" : "Stefan" ,
"endedAtMS" : { "$gt":1301284969946,
"$lt" : 1321284969946}}).
sort({endedAtMS:-1}).
limit(30).
explain()
{
"cursor" : "BtreeCursor player_1_endedAtMS_-1",
"nscanned" : 126,
"nscannedObjects" : 126,
"n" : 30,
"millis" : 1,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"player" : [
[
"Stefan",
"Stefan"
]
],
"endedAtMS" : [
[
1.7976931348623157e+308,
1301284969946
]
]
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,需要扫描126个文档才能获得30个文档.如果你看看explain输出中的indexBounds,似乎只有第一个运算符用于限制索引中的搜索空间.
我错过了什么?为什么Mongo只使用一个运算符来限制搜索空间?
这是一个已知的问题.简短的回答是它与使用多键索引("播放器"是一个数组)的事实有关,并且索引不能在上限和下限上受到约束.
这在Jira案例中有更详细的解释:https://jira.mongodb.org/browse/SERVER-4155 - "索引绑定不正确?"
有一个开放的Jira票可以改善这种行为:https://jira.mongodb.org/browse/SERVER-4180 - "为日期范围查询(回归)选择了错误的索引边界",预计将在2.1版中发布. 2(此版本可能会有变化).请投票给它!
归档时间: |
|
查看次数: |
30492 次 |
最近记录: |