Java 如何在没有OutOfMemoryError的情况下迭代大型Mongo集合

Java 如何在没有OutOfMemoryError的情况下迭代大型Mongo集合,java,mongodb,spring-boot,spring-data,Java,Mongodb,Spring Boot,Spring Data,在我的Spring应用程序中,我希望迭代Mongo集合以对每个条目执行一些工作。集合可能相当大,因此不能简单地获取所有条目的列表,因为这将导致OutOfMemoryErrors 我最近的尝试是: void m(MongoOperations ops, Set<String> ids) { Query query = new Query().addCriteria(Criteria.where("id").in(ids)); CloseableIterator<Foo

在我的Spring应用程序中,我希望迭代Mongo集合以对每个条目执行一些工作。集合可能相当大,因此不能简单地获取所有条目的列表,因为这将导致OutOfMemoryErrors

我最近的尝试是:

void m(MongoOperations ops, Set<String> ids) {
   Query query = new Query().addCriteria(Criteria.where("id").in(ids));
   CloseableIterator<Foo> it = ops.stream(query, Foo.class);
   it.forEachRemaining(foo -> {
       System.out.println(foo.getName());
   }
}
更新: 此后,我尝试通过对查询设置限制并对其排序来实现分页,然后重复跳过条目,直到遍历所有内容。虽然这确实解决了我的内存问题,但它显著降低了性能(大约慢100倍),可能是因为需要排序


我使用的是Spring Boot 1.3.7

游标的内存限制为16 MB,您可能需要编写应用程序级循环,通过使用skip and limit和sorting来挑选批次,例如1000

首先选择1000,然后选择1000到2000,依此类推,直到文档结束,确保在查询中使用排序,以便数据一致


此外,如果要修改要查询和排序的字段,则必须注意,以避免重复出现相同的数据

游标应用了16MB的内存限制,您可能需要编写应用程序级循环,通过使用skip and limit和sorting来选择批量(比如1000批)

首先选择1000,然后选择1000到2000,依此类推,直到文档结束,确保在查询中使用排序,以便数据一致


此外,如果要修改要查询和排序的字段,则必须注意,以避免重复出现相同的数据

您可以共享您的副本集配置吗?rs.status()输出?主数据中心和辅助数据中心是否在同一数据中心?是否确定光标存在内存问题?游标设计为在两种模式下工作:数组或迭代器。在数组模式下,它获取所有内容并将其存储在arraylist中,但在迭代器模式下,它会批量获取它们,而不会将它们保存在内存中。Spring data ClosableTerator实现不调用toArray()模式。所以从技术上讲,它不应该扎根于那里。为什么不把堆转储也添加到这里,让我们看看。我想我没有副本集配置。调用
mongoClient时,返回getReplicaSetStatus()
null
。我已经在原始问题中添加了堆转储的一部分。您是否尝试过使用更新版本的Java驱动程序?看起来
queryResulterator
在3.x版本中不再存在。我检查了Spring数据源,我们没有调用任何预加载方法AFAICS。您可以共享您的副本集配置吗?rs.status()输出?主数据中心和辅助数据中心是否在同一数据中心?是否确定光标存在内存问题?游标设计为在两种模式下工作:数组或迭代器。在数组模式下,它获取所有内容并将其存储在arraylist中,但在迭代器模式下,它会批量获取它们,而不会将它们保存在内存中。Spring data ClosableTerator实现不调用toArray()模式。所以从技术上讲,它不应该扎根于那里。为什么不把堆转储也添加到这里,让我们看看。我想我没有副本集配置。调用
mongoClient时,返回getReplicaSetStatus()
null
。我已经在原始问题中添加了堆转储的一部分。您是否尝试过使用更新版本的Java驱动程序?看起来
queryResulterator
在3.x版本中不再存在。我检查了Spring数据源,我们没有调用任何预加载方法AFAICS。恐怕我不明白。这个16MB的限制是什么?它与我的游标在上面的示例中使用的1.5 GB堆空间有什么关系?MongoDB服务器对find()调用返回的游标设置了一个限制。我认为这是一个健全的检查,意味着它只能在内存中为一个查询调用加载那么多数据。这和你的操作系统内存没有什么关系。恐怕我不明白。这个16MB的限制是什么?它与我的游标在上面的示例中使用的1.5 GB堆空间有什么关系?MongoDB服务器对find()调用返回的游标设置了一个限制。我认为这是一个健全的检查,意味着它只能在内存中为一个查询调用加载那么多数据。它与您的操作系统内存无关。
Class Name                                                                                                           | Shallow Heap | Retained Heap | Percentage
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
org.example.server.OrganizationScopedThreadFactory$OrganizationScopedThread @ 0x81f71718  pool-1-thread-1 Thread|          128 | 1,453,308,456 |     87,50%
|- org.springframework.data.mongodb.core.MongoTemplate$CloseableIterableCursorAdapter @ 0x8b2df1c0                   |           24 | 1,432,708,656 |     86,26%
|  |- com.mongodb.DBCursor @ 0x8b3bb0f8                                                                              |           96 | 1,432,708,600 |     86,26%
|  |  |- com.mongodb.QueryResultIterator @ 0x8b5e7c70                                                                |           72 | 1,431,064,320 |     86,16%
|  |  |  |- java.util.ArrayList$Itr @ 0x8b5e7cb8                                                                     |           32 | 1,431,064,152 |     86,16%
|  |  |  |  '- java.util.ArrayList @ 0x8b5e7cd8                                                                      |           24 | 1,431,064,120 |     86,16%
|  |  |  |     '- java.lang.Object[30391] @ 0x8b5e8ed8                                                               |      121,584 | 1,431,064,096 |     86,16%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8c2eed70                                                          |           64 |       123,528 |      0,01%
|  |  |  |        |  |- java.util.LinkedHashMap$Entry @ 0x8c2eef18                                                   |           40 |       122,240 |      0,01%
|  |  |  |        |  |  |- com.mongodb.BasicDBList @ 0x8c2eef78                                                      |           32 |       122,144 |      0,01%
|  |  |  |        |  |  |  '- java.lang.Object[10] @ 0x8c2eef98                                                      |           56 |       122,112 |      0,01%
|  |  |  |        |  |  |     '- com.mongodb.DBRef @ 0x8c2eefd0                                                      |           32 |       122,056 |      0,01%
|  |  |  |        |  |  |        |- com.mongodb.BasicDBObject @ 0xc5dbc778                                           |           64 |       121,992 |      0,01%
|  |  |  |        |  |  |        |- org.bson.types.ObjectId @ 0x8c2eeff0                                             |           32 |            32 |      0,00%
|  |  |  |        |  |  |        '- Total: 2 entries                                                                 |              |               |           
|  |  |  |        |  |  |- java.lang.String @ 0x8c2eef40  projects                                                   |           24 |            56 |      0,00%
|  |  |  |        |  |  '- Total: 2 entries                                                                          |              |               |           
|  |  |  |        |  |- java.util.LinkedHashMap$Entry @ 0x8c2eee00                                                   |           40 |         1,024 |      0,00%
|  |  |  |        |  |- java.util.LinkedHashMap$Entry @ 0x8c2eeea0                                                   |           40 |           120 |      0,00%
|  |  |  |        |  |- java.util.HashMap$Node[16] @ 0x8c2eedb0                                                      |           80 |            80 |      0,00%
|  |  |  |        |  '- Total: 4 entries                                                                             |              |               |           
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bcfd4c0                                                          |           64 |       123,480 |      0,01%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8c48e2c8                                                          |           64 |       113,520 |      0,01%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8c66f668                                                          |           64 |       112,296 |      0,01%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8c87afe0                                                          |           64 |       112,120 |      0,01%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8c521008                                                          |           64 |       106,096 |      0,01%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8cdc68d0                                                          |           64 |        99,576 |      0,01%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8c8efa40                                                          |           64 |        90,456 |      0,01%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8b8e0d18                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bbc5a30                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bc446e8                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bcc0ca0                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bda1d30                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8be46048                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8be462e8                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8beb24f8                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8beb2798                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bee79d0                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bf04f38                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bf0eae8                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bf0ed88                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bf14220                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bf3edf0                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bf78640                                                          |           64 |        77,600 |      0,00%
|  |  |  |        |- com.mongodb.BasicDBObject @ 0x8bf7dd30                                                          |           64 |        77,600 |      0,00%
|  |  |  |        '- Total: 25 of 30.276 entries; 30.251 more                                                        |              |               |           
-----------------------------------------------------------------------------------------------------------------------------------------------------------------