Performance 虽然设置了索引,但简单MongoDB查询速度非常慢
我有一个MongoDB收藏,里面有大约1亿份文档 文档基本上如下所示:Performance 虽然设置了索引,但简单MongoDB查询速度非常慢,performance,mongodb,indexing,Performance,Mongodb,Indexing,我有一个MongoDB收藏,里面有大约1亿份文档 文档基本上如下所示: _id : ObjectId("asd1234567890") _reference_1_id : ObjectId("fgh4567890123") _reference_2_id : ObjectId("jkl7890123456") name : "Test1" id : "4815162342" created_time : Date( 1
_id : ObjectId("asd1234567890")
_reference_1_id : ObjectId("fgh4567890123")
_reference_2_id : ObjectId("jkl7890123456")
name : "Test1"
id : "4815162342"
created_time : Date( 1331882436000 )
_contexts : ["context1", "context2"]
...
设置了一些索引,下面是db.mycoll.getIndexes()的输出
当我执行如下查询时
db.mycoll.find({"_reference_2_id" : ObjectId("jkl7890123456")})
不管是否有结果,它都需要一个多小时(!)才能完成。
有什么想法吗
更新:
下面是我们的输出
db.mycoll.find({"_reference_2_id" : ObjectId("jkl7890123456")}).explain();
看起来像:
{
"cursor" : "BasicCursor",
"nscanned" : 99209163,
"nscannedObjects" : 99209163,
"n" : 5007,
"millis" : 5705175,
"nYields" : 17389,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
我会尝试在
\u reference\u 2\u id
上设置一个非唯一索引,因为目前,我怀疑您将执行相当于完整表扫描的操作,因为即使索引包含\u reference\u 2\u id
,它们也不会被使用(请参见)。您没有mongo将自动用于该操作的任何索引,所以它在做一个全表扫描
如中所述
如果查询中不存在[索引的]第一个键,则只有在明确提示的情况下才会使用索引
为什么
如果您在a、b上有一个索引-并且您仅通过a
进行搜索-将自动使用索引。这是因为它是索引的开始(这很快就能完成),db可以忽略其余的索引值
仅通过b
进行搜索时,a,b上的索引效率低下,因为它不允许使用“从thisfixedstring开始”的索引搜索
因此,要么:
- 在查询中包含_reference_1_id(可能不相关)
- 或者在_reference_2_id上添加索引(如果经常按字段查询)
- 或者使用提示
\u reference\u 1\u id\u 1\u reference\u 2\u id\u 1\u id\u 1
索引。这可能比完整表扫描快得多,但仍然比以查询中使用的字段开头的索引慢得多
i、 e
惠,
我在同等数量的数据上解决了同样的问题。在文档中,有人写道,带有索引的查询必须适合ram。我认为情况并非如此,查询必须进行大量磁盘访问才能首先检索索引,然后获取值。在您的情况下,直接收集读取将更快
EV.查看explain()的输出(请参见更新的问题),您是对的,我正在进行一次不使用索引的全表扫描。但为什么会这样呢?我在MongoDB文档中看不到关于这方面的任何信息。太好了,非常感谢您的详细回答!实际上,我可以包含_reference_1_id,因此我甚至不需要提示索引。
{
"cursor" : "BasicCursor",
"nscanned" : 99209163,
"nscannedObjects" : 99209163,
"n" : 5007,
"millis" : 5705175,
"nYields" : 17389,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
db.mycoll
.find({"_reference_2_id" : ObjectId("jkl7890123456")})
.hint("_reference_1_id_1__reference_2_id_1_id_1");