首次阅读

时间:2017-10-02 09:39:11

标签: mongodb mongodb-query

我需要查询大量文件(> 100M),并且我要批量申请5000份文件(每份约4-5MB)。 出于某种原因,第一个请求(没有_id过滤)快速返回(~1.5s)而 休息需要很长时间(约8-9.5秒)。

现在,当批量阅读500份文件(每份约500kB)时,时间明显更好(~0.5-0.8s),并且对于每个请求都是一致的。

我使用_id + limit分页方法,因为我看到skip + limit方法执行得更糟。

这是我的流程示例。

var mongodb = require("mongodb")
var bytes = require("bytes")

...

var filter = {
    '_id': { '$gt': this._lastId }
}

if(mongodb.ObjectId.isValid(this._lastId)) {
    filter['_id'] = { '$gt': this._lastId }
}

var cursor = this.conn.collection(collectionName)
    .find(filter)
    .limit(5000)

var start = new Date().getTime()
cursor.toArray(function(err, docs) {
    if (err) { ... }

    var elapsed = (new Date().getTime() - start) / 1000

    console.log(
        "Docs:", docs.length,
        "Size:", bytes(sizeof(docs)),
        "Took:", elapsed + " seconds"
    )

    var lastDoc = docs[docs.length - 1]

    this._lastId = lastDoc._id
})

...

1 个答案:

答案 0 :(得分:1)

我发现问题很有趣,试图重现它并得出相同的结果:从id 0到5000的第一次调用很快,而其他所有调用都持续时间更长(大约7x)

这与没有过滤器的阅读有关。如果你在mongo shell中运行你的命令并对你的查找做一个解释,你会发现当从0到5000读取时没有应用过滤器。

您可以使用.batchSize()一次获取更多文档(根据您的数字,每个文档大约1KB)。每个游标迭代的默认值为20。 当您运行.toArray()函数时,它将从MongoDB向您的应用程序发送20KB的块,直到传输5000个文档。使用更大的批次可能会更优化,你应该尝试不同的值,但我会从500开始一次获得500KB,因为它减少了小块的网络开销。 您可能还会发现cursor.forEach()在处理数据时会更好地工作(通过batchSize(n)的块)。在这种情况下,如果您查询整个集合或5000块,如果最后要检查所有文档,则无关紧要。

游标保持连接打开并在MongoDB服务器上分配资源,直到您关闭游标或与数据库的连接,但光标的大小不会增加它只保存批处理数据。

另一方面,我认为做小批量的速度并不快:每个文档的时间相似,文档少10倍,速度快10倍。