2014-10-30 54 views
2

我正在使用Solr进行全文搜索并将Mongodb用作持久性存储的项目。基本上在Solr中搜索返回Mongo ID,然后我们用它来获取文档。

问题是,一些Solr搜索以数千Ids的顺序返回结果。这些结果实际上是我们所期望的,因此Solr在这里没有问题。当我们想从MongoDB中获取10k的Ids时,问题就出现了。查询使用$ in,但时间过长;在检查了mongodb分析器之后,似乎mongo花费了很多时间来获取读锁。

任何替代方法?,可能仍然使用$ in,但将Ids设置为更小的块?

作为一个侧面说明,我们使用的是Java 8,使用Spring 4.0和Spring数据蒙戈1.6

此外,作为附加信息,收集有13万份文件,每个文件大小平均11KB 。

这里查询的例子:

{"_id" : { 
     "$in" : [ 
      ObjectId("5441614a5d28a9872823694c"), 
      ObjectId("544155eb5d28a987281aa112"), 
      ObjectId("5441500e5d28a9872815b917"), 
      ObjectId("544153285d28a987281877b9"), 
      ObjectId("544159095d28a987281c1f5c"), 
      ObjectId("54415b105d28a987281d3ad7"), 
      ObjectId("54415a995d28a987281cf0e6"), 
      ObjectId("544160215d28a9872822383b"), 
      ObjectId("544160e85d28a98728230342"), 
      ObjectId("544157ba5d28a987281b7dea"), 
      ObjectId("54415e375d28a9872820508b"), 
      ObjectId("544150f75d28a98728169563"), 
      ObjectId("54415c6b5d28a987281e8bcb"), 
      ObjectId("54415a6d5d28a987281cd704").............]}} 

这是一个小的一套解释的结果:

{ 
"cursor" : "BtreeCursor _id_ multi", 
"isMultiKey" : false, 
"n" : 14, 
"nscannedObjects" : 14, 
"nscanned" : 27, 
"nscannedObjectsAllPlans" : 14, 
"nscannedAllPlans" : 27, 
"scanAndOrder" : false, 
"indexOnly" : false, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"millis" : 0, 
"indexBounds" : { 
    "_id" : [ 
     [ 
      ObjectId("5441500e5d28a9872815b917"), 
      ObjectId("5441500e5d28a9872815b917") 
     ], 
     [ 
      ObjectId("544150f75d28a98728169563"), 
      ObjectId("544150f75d28a98728169563") 
     ], 
     [ 
      ObjectId("544153285d28a987281877b9"), 
      ObjectId("544153285d28a987281877b9") 
     ], 
     [ 
      ObjectId("544155eb5d28a987281aa112"), 
      ObjectId("544155eb5d28a987281aa112") 
     ], 
     [ 
      ObjectId("544157ba5d28a987281b7dea"), 
      ObjectId("544157ba5d28a987281b7dea") 
     ], 
     [ 
      ObjectId("544159095d28a987281c1f5c"), 
      ObjectId("544159095d28a987281c1f5c") 
     ], 
     [ 
      ObjectId("54415a6d5d28a987281cd704"), 
      ObjectId("54415a6d5d28a987281cd704") 
     ], 
     [ 
      ObjectId("54415a995d28a987281cf0e6"), 
      ObjectId("54415a995d28a987281cf0e6") 
     ], 
     [ 
      ObjectId("54415b105d28a987281d3ad7"), 
      ObjectId("54415b105d28a987281d3ad7") 
     ], 
     [ 
      ObjectId("54415c6b5d28a987281e8bcb"), 
      ObjectId("54415c6b5d28a987281e8bcb") 
     ], 
     [ 
      ObjectId("54415e375d28a9872820508b"), 
      ObjectId("54415e375d28a9872820508b") 
     ], 
     [ 
      ObjectId("544160215d28a9872822383b"), 
      ObjectId("544160215d28a9872822383b") 
     ], 
     [ 
      ObjectId("544160e85d28a98728230342"), 
      ObjectId("544160e85d28a98728230342") 
     ], 
     [ 
      ObjectId("5441614a5d28a9872823694c"), 
      ObjectId("5441614a5d28a9872823694c") 
     ] 
    ] 
}, 
"server" : "0001a22df018:27017" 

}

+0

集合有哪些索引?在该查询上输出'.explain()'? – BluePeppers 2014-10-30 17:27:43

+0

你会用10k文件做些什么?当然不会将它们全部显示给用户。或者,也许这是出口的某种? – helmy 2014-10-30 17:40:26

+0

我们根据文档中的数据进行了一些计算,并在文档中删除了很多文档,最后我们列出了一个10 – xburgos 2014-10-30 17:44:02

回答

1

也许这些信息都可以给一个帮助,仅供参考。

集合的大小大于1.3M X 11K = 14.6GB(一个不小)
要查询的文档的速度为10K/1.3M = 0.75%

的文件索引并找到任何一个应该是非常快的。但收集很大。由于您没有提供有关ID的信息,我只是假设这些ID的文档分布几乎是任意的。首先,MongoDB可能会尝试从内存中查找所有文档。当再次找不到时,它会根据其余的ID将新的数据从磁盘加载到内存中,并重复搜索直到最后完成工作。从磁盘加载时间可能是决定查询性能的主要因素。加载时间取决于您的ID的分布情况。如果它们在分布上非常密集,则查询应该非常快,否则它可能会变慢。所以,速度取决于您正在搜索的文档的分布情况。

使用分片集合(更多分片实例)可能会提供一些帮助。

+0

嗨向导,非常感谢!我接受了您的解决方案,因为您提到的内容是问题的一部分,另一部分是我们试图获取太多数据的事实,但是,即使分片现在不是我们的选择,我们选择了一种允许我们获取的解决方案文档的“意见”,而不是spring-data-mongo,它只适用于完整的文档。 – xburgos 2014-10-31 17:29:39

+0

@Cybrid:恭喜你有一个解决方案。顺便说一下,获取文档的部分字段是MongoDB的投影功能,spring-data-mongo只是中继客户端的命令。这意味着您只能从每个文档中获取多个字段,但不能获取整个11KB字段。那么为什么你说它只适用于完整的文档?或者我错过了你的话? :) – Wizard 2014-11-01 03:38:33