2

我正在将 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 个项目需要将近一分钟。

我可以做任何优化来加快速度吗?

4

2 回答 2

3

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

  • 您读取 CSV 文件的方式取决于您加载它的方式,您可以将其完全加载到内存中(使用file_get_contents()或例如),或者使用,file()逐块读取它。fopen()fread()

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

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

可以使用$entityManager->clear();

clear()清除整体EntityManager,您想清除单个实体,您可以使用$entityManager->detach($object).


如果您想分析您的内存使用情况,您可能还对这些功能感兴趣

memory_get_usage()

memory_get_peak_usage()

于 2012-10-18T15:17:48.480 回答
1

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

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

于 2012-10-18T13:05:28.450 回答