我正在使用Doctrine和MongoDB作为应用程序,并且有一个任务应将CSV文件中的数据导入集合。大约有5个不同的CSV文件,每个文件至少有450.000个条目,每年应很重要。
当前我遍历文件的所有行,创建对象,调用persist()
并每2.500个项目冲洗。
每个项目不是很大,它具有一个ID,一个字符串为10-20个字符,字符串为5-10个字符和一个布尔值。
我的第一个问题是:当我冲洗每5.000个物品时,插入的时间大大降低。在我的测试环境中,冲洗5.000件大约102秒,冲洗2.500个物品大约需要10秒。
一段时间后冲洗速度较慢。如前所述,在开始时冲洗2.500个物品大约需要10秒钟,100.000个物品,冲洗2.500个物品需要将近一分钟。
我可以做任何优化来加快速度吗?
我认为您的脚本中可能会优化两个部分。
- 您读取CSV文件的方式,具体取决于加载方式,您要么将其完全加载到内存中(例如使用
file_get_contents()
或file()
),或者使用fopen()
,fread()
。
最优选的选项是因为它仅在处理一系列行时才需要必要的内存数量。
- 您需要
clear()
您已经处理过的对象,否则它将保存在内存中,直到脚本结束为止。这意味着,如果一个DC2对象使用1MO的内存,并且您有100,000个对象,那么在脚本的末尾,它将使用100,000mo。因此,按2500范围批量插入是一个很好的主意,但是您显然需要从EntityManager中删除处理后的对象。
可以使用$entityManager->clear();
clear()
将清除整个EntityManager
,您要清除一个实体,您可以使用$entityManager->detach($object)
。
如果要介绍您的内存使用量,则可能也对功能感兴趣
memory_get_usage()
memory_get_peak_usage()
是否有任何理由此导入脚本需要使用该学说ODM?对于整个应用程序,当然。但是,处理大量数据的大量数据并不是最佳的数据,因为PHP在持有和处理大型收藏方面并不那么有效。
您可以做的最好的优化是跳过该图层并直接使用MongoDB类,并确保您逐行读取文件,而不是一次读取文件。同样,如果您有一些网络延迟到mongoDB(但是您不需要将其推到5K文档)。