使用Doctrine将大量数据插入MongoDB集合

时间:2012-10-18 12:54:23

标签: php mongodb doctrine-orm

我正在使用Doctrine和MongoDB作为应用程序,并且有一项任务应该将CSV文件中的数据导入到集合中。大约有5种不同的CSV文件,每个文件至少有450.000个条目,每年应该重要1到3次。

目前,我遍历文件的所有行,创建一个对象,调用persist()并刷新每个2.500项。

每个项目都不是很大,它有一个ID,一个10-20个字符的字符串,一个5-10个字符的字符串和一个布尔值。

我的第一个问题是: 当我冲洗每个5.000项时,插入速度明显变慢。在我的测试环境中,冲洗5.000件物品需要大约102秒,冲洗2.500件物品大约需要10秒钟。

一段时间后,法拉盛会变慢。如上所述,在开始时冲洗2.500件物品大约需要10秒钟,在完成100,000件物品后,冲洗2.500件物品需要将近一分钟。

我可以做些什么来加快速度吗?

2 个答案:

答案 0 :(得分:2)

我认为您的脚本中有两个部分可以优化。

  • 您阅读CSV文件的方式,取决于您加载它的方式,您可以将其完全加载到内存中(例如,使用file_get_contents()file()),或者通过chunck with { {1}},fopen()

最后一个选项是首选,因为它只会在处理一堆行时占用必要的内存量。

  • 您需要fread()已处理的对象,否则它将保留在内存中直到脚本结束。这意味着如果一个DC2对象使用1Mo内存,并且您有100,000个对象,则在脚本末尾将使用100,000Mo。 因此,按照2,500的范围对插入进行批处理是个不错的主意,但显然需要从EntityManager中删除已处理的对象。

可以使用clear()

完成

$entityManager->clear();将清除整个clear(),您想要清除单个实体,您可以使用EntityManager


如果您想了解您的内存使用情况,您可能也会对这些功能感兴趣

memory_get_usage()

memory_get_peak_usage()

答案 1 :(得分:0)

这个导入脚本是否需要使用Doctrine ODM?对于整个应用程序 - 当然。但是处理大量开销的数据并不是最理想的,因为PHP在保存和处理大型集合方面效率不高。

您可以做的最佳优化是跳过该层并直接使用mongodb类,并确保您逐行读取文件而不是一次读取所有文件。如果您对MongoDB有一些网络延迟(但是您不需要将其推送到5k文档),那么使用batchInsert()会加快您的速度。