我最近需要优化我们 MongoDB 上的某些查询,并遇到了这个特定的问题:
假设我有一个查询,匹配
现在问题来了:mongodb认为BasicCursor比这个索引更好。如果我使用
为了高效地查询它,我们需要像下面这样的额外索引吗?坦白说,我不确定MongoDB查询优化器会如何处理它们。
这是我的查询带或不带提示的解释。
我在
感觉很奇怪。
假设我有一个查询,匹配
A
和 B
,然后在 C
上进行范围选择,并通过对 D
进行排序来输出结果,在 shell 中它们看起来像这样:db.collection.find({ A: 'something', B: 'something-else', C: { $gt: 100 } })
.sort({ D: -1 }).limit(10)
去年我阅读了一篇文章,讲述了为这种情况创建索引的基本规则:
- 精确匹配字段优先
- 排序字段其次
- 范围搜索($in、$gt等)字段最后
他们的解释看起来很合理,所以我按照此方式创建了一个索引:
db.collection.ensureIndex({ A:1, B:1, D:-1, C:-1 })
现在问题来了:mongodb认为BasicCursor比这个索引更好。如果我使用
hint
全索引,它可以工作(并且速度更快),但这样做需要对我们的代码库进行相当多的更改,因此我们尽可能避免这种情况。
我的问题是:
当我的查询包含所有4个字段时,为什么mongodb查询优化器会决定选择
{ A:1, E:-1 }
,{ D:-1 }
甚至是BasicCursor比{ A:1, B:1, D:-1, C:-1 }
更好。{ A:1, D:-1 }
是否多余,mongo docs确实说使用部分索引不太有效率?
此外,我们还有以下查询:
db.collection.find({ A: { $in : ['str1','str2'] }, B: 'something', C: { $gt: 100 } })
.sort({ D: -1 }).limit(10)
为了高效地查询它,我们需要像下面这样的额外索引吗?坦白说,我不确定MongoDB查询优化器会如何处理它们。
db.collection.ensureIndex({ B:1, D:-1, C:-1, A:1 })
这是我的查询带或不带提示的解释。
- 带提示 (全索引): http://pastebin.com/xtpJ3dsf
- 带提示 (A,D索引): http://pastebin.com/v66QmtsP
- 不带提示: http://pastebin.com/QAtM0WN0
- 不带提示 (放弃其他索引): http://pastebin.com/6ZDweiNX
{ A:1, E:-1 }
而不是 { A:1, D:-1 }
,这似乎更奇怪,因为我们没有在字段 E 上进行查询。我在
{ A:1, E:-1 }
上删除了索引,现在解释告诉我它默认为{ D:-1 }
,所以我也删除了它,现在MongoDB开始使用BasicCursor
... 它似乎不喜欢我的完整索引或A:1, D:-1
索引(尽管提示结果表现更好)。感觉很奇怪。