【问题标题】:Poor performance for traversing all the documents from mongodb using Java使用 Java 从 mongodb 遍历所有文档的性能不佳
【发布时间】:2012-11-06 09:50:13
【问题描述】:

我将系统日志存储在 mongodb 中,并根据“时间”字段构建索引。 mongodb 现在大约有 190k 日志。 当我尝试使用 Java 中的 DBCollection.find() 方法获取所有日志时,它花费了将近 10 秒来遍历集合中的所有文档。我认为可能是我错过了什么导致性能不佳?

这是我使用的代码:

mongo = new Mongo();
DB db = mongo.getDB("Log");
DBCollection coll = db.getCollection("SystemLog");
int count = 0;

long findStart = Calendar.getInstance().getTimeInMillis();

// Sort by time.
BasicDBObject queryObj = new BasicDBObject();
queryObj.put("time", -1);

DBCursor cursor = coll.find().sort(queryObj);
while(cursor.hasNext()) {
    DBObject obj = cursor.next();
    // Do something
    ++count;
}
long findEnd = Calendar.getInstance().getTimeInMillis();
System.out.println("Time for traversing all system logs (" + count + "):\t" + (findEnd-findStart) + "ms.");

打印出来的结果是:

Time for traversing all system log (194309):    10496ms.

我已经试过好几次了。运行一次或多次似乎没有区别。虽然我也尝试删除 sort() 并从 mongodb 中找到所有日志。遍历所有文档大约需要 6 秒。时间对于我的要求来说还是有点难以接受。有没有可以加快遍历工作的实现技巧?

非常感谢。

【问题讨论】:

    标签: java mongodb mongodb-java


    【解决方案1】:

    你真的需要遍历所有文档吗?在上面的代码中,您似乎只是将每个对象一个一个地带入内存。

    1. “时间”字段的索引应构造为“降序”,因为您是这样排序的。
    2. 如果索引是复合索引(索引中有更多字段,而不仅仅是“时间”),请确保您还添加了一个仅包含“时间”的索引。此外,当您向该查询添加过滤器时,请确保“时间”字段最后添加到索引中并降序排列。
    3. 考虑到您正在逐个读取 190k 个对象,性能还不错。

    (请注意,我使用 mongodb 的经验不涉及使用 Java 驱动程序)

    【讨论】:

    • 感谢您的回复和建议。是的,我需要遍历所有文档。实际上我需要做的是将所有日志从mongodb导出到一个文件中,因此我必须将文档一个一个地放入内存(并将它们写入一个固定格式的文本文件)。但是,我希望这项工作可以在不超过 5 秒的时间内完成,因为在生成日志文件后,用户必须再等待几秒钟才能下载日志文件。
    • 确保时间降序的索引在那里。另外,我会尝试一次获得几 k 的对象。限制并跳过查询(Java驱动程序应该处理这个)并以块的形式获取对象。查看 mongo 分析器以查看那里发生了什么。最好的情况是你会看到一个游标,它每次都以完全索引的方式返回大块对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 2021-05-06
    • 2012-05-28
    • 2012-12-17
    • 2017-04-15
    相关资源
    最近更新 更多