使用$ in运算符的id对Mongodb查询大量的ID是太慢了,替代方案?

时间:2014-10-30 17:22:25

标签: mongodb mongodb-query spring-data-mongodb

我正在开发一个项目,该项目使用Solr进行全文搜索,将Mongodb用作持久存储。基本上在Solr中搜索返回Mongo id,然后我们用它来获取文档。

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

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

作为旁注,我们正在使用Java 8,Spring 4.0和Spring-Data-Mongo 1.6

此外,作为附加信息,该馆藏有130万份文件,每份文件平均大小为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"

}

1 个答案:

答案 0 :(得分:1)

也许这些信息可以提供帮助,仅供参考。

集合的大小大于1.3M x 11K = 14.6GB(不小) 您要查询的文档的比率是10K / 1.3M = 0.75%

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

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