我正在使用tFileInputJson和tMongoDBOutput组件将JSON数据存储到MongoDB数据库中。
使用少量数据(近100k JSON对象)尝试此操作时,数据可以存储到数据库中而不会出现任何问题。
现在我的要求是将近300k的JSON对象存储到数据库中,我的JSON对象如下所示:
{
"LocationId": "253b95ec-c29a-430a-a0c3-614ffb059628",
"Sdid": "00DlBlqHulDp/43W3eyMUg",
"StartTime": "2014-03-18 22:22:56.32",
"EndTime": "2014-03-18 22:22:56.32",
"RegionId": "10d4bb4c-69dc-4522-801a-b588050099e4",
"DeviceCategories": [
"ffffffff-ffff-ffff-ffff-ffffffffffff",
"00000000-0000-0000-0000-000000000000"
],
"CheckedIn": false
}
当我执行此操作时,我收到以下异常:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
[statistics] disconnected
at java.util.Arrays.copyOf(Arrays.java:2367)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415)
at java.lang.StringBuffer.append(StringBuffer.java:237)
at org.json.simple.JSONArray.toJSONString(Unknown Source)
at org.json.simple.JSONArray.toJSONString(Unknown Source)
at org.json.simple.JSONArray.toString(Unknown Source)
at samplebigdata.retail_store2_0_1.Retail_Store2.tFileInputJSON_1Process(Retail_Store2.java:1773)
at samplebigdata.retail_store2_0_1.Retail_Store2.runJobInTOS(Retail_Store2.java:2469)
at samplebigdata.retail_store2_0_1.Retail_Store2.main(Retail_Store2.java:2328)
Job Retail_Store2 ended at 15:14 10/11/2014. [exit code=1]
我目前的工作如下:
如何在一个作业中将如此多的数据存储到数据库中?
答案 0 :(得分:1)
这里的问题是您将JSON对象打印到控制台(使用tLogRow)。这需要将所有JSON对象保存在内存中,然后在" flow"之后最终一次性转储到控制台。完成了。
如果删除了tLogRow组件,那么(在这么简单的工作中)Talend应该只保存内存中tMongoDbOutput组件的批量大小,并继续将批次推送到MongoDB中。
举个例子,这是我成功将1亿行随机生成的数据加载到MySQL数据库中的截图:
当作为CSV时,数据集在磁盘上代表大约2.5 GB,但是在内存中可以轻松处理,最大堆空间为1 gb,因为每个插入行为100行,因此作业实际上只需要保留100行CSV(加上任何一点内存中的任何关联元数据和任何Talend开销。
实际上,它可能会比内存中的内容大得多,只是在接近最大内存时垃圾收集已插入数据库的行。
如果您绝对需要记录成功放入数据库的JSON记录,那么您可以尝试输入到文件中并输出输出。
只要你没有在tFileInputJson中获得太多无效的JSON对象,那么你可以保持拒绝链接的tLogRow,因为它只会收到被拒绝/无效的JSON对象,因此不应该用完记忆由于您在32位系统上受限于少量内存,因此您可能需要小心,如果无效JSON对象的数量增加,您将很快超出内存空间。
如果您只是想将大量JSON对象加载到MongoDB数据库,那么最好使用tMongoDBBulkLoad组件。这需要一个平面文件(.csv .tsv或.json)并将其直接加载到MongoDB数据库中。我刚刚链接的文档显示了所有相关选项,但您可能对可以传递给数据库的--jsonArray
附加参数特别感兴趣。还有一个如何使用该组件的基本示例。
这意味着您无法在加载过程中进行任何处理,并且您必须使用预先准备好的json / csv文件来加载数据,但是如果您只是想快速将数据加载到数据库中使用Talend然后这应该涵盖它。
如果您需要一次处理文件的块,那么您可能希望通过循环查看更复杂的作业,从输入中加载 n 记录,处理它们然后重新启动循环的处理部分,但选择带有 n 记录标题的 n 记录,然后用 2n 记录的标题重复,依此类推...
Garpmitzn's answer几乎涵盖了如何更改JVM设置以增加内存空间,但对于像这样简单的事情,你只想减少你没有充分理由保留在内存中的数量。
顺便说一句,如果您要支付Talend的企业许可证,那么您应该能够轻松地获得一个64位的容量16 GB的内存盒,这将极大地帮助您的开发。我至少希望您的生产作业执行服务器有一堆内存。
答案 1 :(得分:0)
我觉得你正在阅读talend的记忆。你必须使用像Xms和XmX这样的Java JVM参数 - 你可以增加Xmx来说明当前设置的大小,如果它设置为Xmx2048然后将其增加到Xmx4096或其他...
这些参数在导出作业的.bat / .sh文件中可用,或者在talend studio中,您可以在“运行作业”选项卡“高级设置JVM设置...”中找到它们。
但是建议以这样的方式设计工作,使你不要在内存中加载太多..