对于downvote仙女..我知道php是错误的语言...但我在外界限制下工作。鉴于:
我有一个大的平面文件,我需要在php中处理。我将平面文件转换为mysql中的规范化数据库。平面文件中有几百万行。
我最初尝试在导入平面文件时使用ORM系统。即使小心地释放对象,该设计也存在大量的php内存泄漏问题。即使我确保有足够的内存,脚本也需要大约25天才能在我的桌面上运行。
我剥离了开销并重写了脚本以直接构建mysql命令。我从我的设计中删除了AUTO INCREMENT,因为这要求我作为Mysql输入的最后一个id是为了在数据点之间建立关系。我只是使用数据库ID的全局计数器,我从不进行任何查找,只需插入。
我使用unix split命令来制作大量小文件而不是一个大文件,因为一次又一次地使用文件指针会产生内存开销。
使用这些优化(希望他们帮助其他人)我让导入脚本在大约6个小时内运行。
我租用了一个虚拟实例,其RAM大5倍,处理器功率大约是我的桌面的5倍,并注意到它的速度完全相同。服务器运行该进程但具有CPU周期和RAM备用。也许限制因素是磁盘速度。但我有很多内存。我应该尝试以某种方式将文件加载到内存中吗?欢迎任何进一步优化处理大文件的php命令行脚本的建议!
答案 0 :(得分:3)
你不会喜欢它但是......听起来你正在使用错误的语言来完成手头的任务。如果你想在速度上获得一些巨大的飞跃,那么下一步就是编译语言的端口。编译语言的运行速度比脚本语言快得多,因此您可以看到处理时间下降。
此外,您可以使用内置命令将数据转储到数据库中。 Postgres有一个(转储?加载?类似的东西),它将在制表符分隔的文本文件中读取,其列与表中的列匹配。这样您就可以专注于以正确的格式获取文本文件,然后使用一个命令将其吐入DB,并让它处理优化而不是您自己。
你已经做了正确的事情,敲击头部的ORM,虽然你的文本文件阅读器应该只在内部使用一个缓冲区,但是不应该需要拆分文件所以它“应该”并不重要但是我不是* nix家伙在那方面可能是错的。
我们已经完成了与.net应用程序类似的事情,每天早上在每行上运行20Gb文件,在每行上执行RegExp,为唯一记录保留内存哈希,然后将新内容写入数据库。然后,我们使用Ruby脚本轻松吐出9000+个JS文件(这是最慢的部分)。我们过去也用Ruby编写了导入器,整个过程需要3个多小时,重新编写.net会在大约30-40分钟内完成整个过程,其中20个是慢速Ruby脚本(不值得再优化了)虽然它做得很好)。
答案 1 :(得分:3)
针对此类任务的几个重要设计建议:
不要一次将整个文件读入内存。使用文件指针并以合理的块读取(例如,几千字节...取决于平均记录大小)。然后处理每个记录并丢弃缓冲区。我从你的描述中不确定你是否已经这样做了。
如果您的mysql存储类型支持事务(表必须是InnoDB),您可以使用它们进行优化。启动交易并处理f.ex. 100k行,然后通过提交事务并打开一个新事务来刷新。这是有效的,因为MySql只会更新索引一次,而不是每行更新一次。
另一种选择是使用批量插入。如果您的数据库不是本地的(例如,您通过网络连接),这可以提升。我认为(不确定)它也提供与交易相同的好处 - 甚至可能用于MyIsam表。
最后,如果没有其他工作,您可以从等式中删除php并使用LOAD DATA INFILE
。您可能必须首先使用php或其他一些文本处理语言预处理文件(awk或sed具有非常好的性能配置文件)
答案 2 :(得分:2)
你花费的时间,在不同机器之间相似,可能是因为PHP脚本和MySQL服务器之间的通信:对于每个MySQL请求:
PHP方面可能并不真正需要时间;最有可能的是,它介于PHP和MySQL之间 - 你可能无法做很多事情。
如果你有一台非常强大的机器,我建议的是:
脚本的第一次并行执行将处理少6倍的数据;其他人也一样......而且他们会并行工作......所以,最后,整个过程可能会花费4倍的时间: - )
可能不会花费6倍的时间:使用并行化意味着在机器上添加一些负载,并且MySQL将在并发中有一些请求 - 但只有几个并行进程,它会没事的。
作为旁注:从PHP执行此操作可能不是最好的选择。这是我能想到的另一种方式:
mysql --host=HOST --user=USER --password=PASSWORD DATABASE_NAME < inserts-commands.sql
”这样,只需确保文件中的SQL请求正常,然后,MySQL一次性导入所有内容:您不必为每个请求从PHP转到MySQL - 它应该更快。
希望这有帮助,玩得开心!
答案 3 :(得分:1)
除了优化脚本之外,您建议尝试使用任何PHP加速器(例如:eaccelerator.net)。如果这没有帮助,我建议使用为此类任务制作的语言/平台。
答案 4 :(得分:0)
几乎所有其他答案都指出了。 PHP不太适合这种处理。
特别是现在HADOOP等人已经基本上使这种特定类型的任务在云中完全可以并行化。
但某个地方的某些人可能需要像我一样使用PHP来处理大型文件。
鉴于此,我应该指出新的Facebook工具xhprof在命令行上运行良好。
如果您发送以下命令以启动:
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY );
您可以轻松查看自己代码的哪些特定部分需要花费很多时间。
HTH,其他任何一个人注定要继续强迫我用方钉钉住一根钉子。-FT