java - MongoDB Java API 读取速度慢

标签 java mongodb performance mongodb-java mongo-java

我们正在从本地 MongoDB 读取集合中的所有文档,性能不是很出色。

我们需要转储所有数据,不要担心为什么,只要相信它确实需要并且没有解决方法。

我们有 4mio 文档,看起来像:

{
    "_id":"4d094f58c96767d7a0099d49",
    "exchange":"NASDAQ",
    "stock_symbol":"AACC",
    "date":"2008-03-07",
    "open":8.4,
    "high":8.75,
    "low":8.08,
    "close":8.55,
    "volume":275800,
    "adj close":8.55
}

我们现在使用这个简单的代码来阅读:

MongoClient mongoClient = MongoClients.create();
MongoDatabase database = mongoClient.getDatabase("localhost");
MongoCollection<Document> collection = database.getCollection("test");

MutableInt count = new MutableInt();
long start = System.currentTimeMillis();
collection.find().forEach((Block<Document>) document -> count.increment() /* actually something more complicated */ );
long start = System.currentTimeMillis();

我们以 16 秒(250k 行/秒)的速度读取整个集合,对于小型文档来说,这真的一点也不令人印象深刻。请记住,我们要加载 800mio 行。不能进行聚合、map reduce 或类似操作。

这是否与 MongoDB 一样快,或者是否有其他方法可以更快地加载文档(其他技术、移动 Linux、更多 RAM、设置...)?

最佳答案

您没有指定用例,因此很难告诉您如何调整查询。 (即:谁愿意一次加载 8 亿行只是为了计数?)。

鉴于您的架构,我认为您的数据几乎是只读的,并且您的任务与数据聚合有关。

您当前的工作只是读取数据,(很可能您的驱动程序将批量读取),然后停止,然后执行一些计算( hell 是的,一个 int 包装器用于更多地增加处理时间),然后重复。这不是一个好方法。如果您没有以正确的方式访问数据库,它就不会神奇地快速。

如果计算不是太复杂,我建议你使用aggregation framework而不是全部加载到您的 RAM 中。

您应该考虑改进聚合:

  1. 将您的数据集分成更小的集合。 (例如:按 date 分区,按 exchange 分区...)。添加索引以支持该分区并在分区上操作聚合,然后组合结果(典型的分而治之方法)
  2. 项目仅需要的字段
  3. 过滤掉不必要的文档(如果可能)
  4. 如果您无法在内存上执行聚合(如果您达到每个管道 100MB 的限制),请允许使用磁盘。
  5. 使用内置管道加快计算速度(例如:$count 用于您的示例)

如果您的计算过于复杂,无法用聚合框架表达,请使用 mapReduce .它在 mongod 进程上运行,数据不需要通过网络传输到您的内存中。

更新

所以看起来您想要进行 OLAP 处理,但您停留在 ETL 步骤。

您不需要也必须避免每次都将整个 OLTP 数据加载到 OLAP。只需要将新的更改加载到您的数据仓库。那么第一次数据加载/转储需要更多时间是正常且可以接受的。

首次加载时,应考虑以下几点:

  1. 分而治之,再次将您的数据分解为更小的数据集(使用日期/交易所/股票标签等谓词...)
  2. 进行并行计算,然后合并结果(您必须正确划分数据集)
  3. 批量计算而不是 forEach 中的处理:加载数据分区然后计算而不是一个一个地计算。

关于java - MongoDB Java API 读取速度慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52101372/

相关文章:

java - 如何在java应用程序中设置垂直选取框?

java - 方法不更改 main 中的数组

Mongodb upsert 只更新选中的字段,但是全部插入

python - 如何获取忽略后缀的所有元素组合?

android - 可见性设置为 "gone"的 View 是否是测量和布局过程的一部分?

java - Android:在没有额外支持库的情况下滑动 View

java - 从 JSON 转换为 Map 的递归函数

Mongodb 聚合与 mongoose 过滤器嵌入文档

node.js - socketTimeoutMS 在非常简单的环境中不起作用

java - 哪个效率更高 : atomically modifying an array or synchronizing access to it?