我有一个Cronjob脚本,用PHP编写,具有以下要求:
脚本在开发过程中运行良好但在生产过程中,步骤1返回了大约5000万条记录。结果,很明显,脚本运行大约4天然后失败。 (粗略估计,以当前的速度,完成需要大约171天)
请注意,我们使用预备语句,第1步是一次获取1000条记录中的数据。
一些测试显示插入(上面的步骤3)占用了最长时间(超过95%的时间)。为了优化,在一些谷歌搜索之后,我们从表中删除了所有索引,而不是一个插入查询/行,我们没有一个插入查询/ 100行。这使我们的插入速度提高了一些,但是根据粗略估计,运行cron一次需要90天,我们需要每月运行一次,因为每个月都有新的数据。
此步骤似乎无效。在CSV文件中写入30000行需要16分钟,我们仍然需要在MySQL中导入该CSV文件。我们为所有写操作都有单个文件处理程序。
看来我现在还无能为力。一些关键要求:
然而:
我不需要任何描述性答案,但有人可以简单地提出可能的解决方案。我只需要一些优化提示,我会留下R& D.
我们对一切开放,更改数据库/存储引擎,服务器优化/多个服务器(数据库和应用程序),更改编程语言或满足上述要求的最佳配置。
最终期望,cron必须在最多24小时内完成。
为了进一步理解为什么生成csv花费时间,我已经创建了我的代码的副本,只有必要的代码。该代码出现在git https://github.com/kapilsharma/xz
上实验的输出文件是https://github.com/kapilsharma/xz/blob/master/csv/output500000_batch5000.txt
如果你检查上面的文件,我一次插入500000条记录并从数据库中获取5000条记录,使循环运行100次。第一次循环所用的时间是0.25982284545898秒,但是在第100次循环中是3.9140808582306。我假设它是因为系统资源和/或csv文件的文件大小。在这种情况下,它变得更多的编程问题然后DB优化。不过,有人可以建议为什么在下一个循环中花费更多时间吗?
如果需要,除了生成csv文件和sql文件以创建虚拟DB之外,整个代码都会被提交,因为这些文件非常大。但是,可以使用代码轻松生成它们。
答案 0 :(得分:2)
我在CakePHP上有一个邮件程序cron作业,它只在600行获取并向注册用户发送电子邮件失败。它甚至不能在批处理操作中执行任务。我们最终选择mandrill,从那时起一切顺利。
我建议(考虑在生产中触摸遗留系统是一个坏主意):
或
希望这有帮助。
答案 1 :(得分:1)
使用OFFSET
和LIMIT
遍历表格是O(N * N),这比你想要或预期的要慢得多。
相反,走过桌子“记住你离开的地方”。最好使用PRIMARY KEY
。由于id看起来像AUTO_INCREMENT
没有间隙,因此代码很简单。 My blog讨论了(以及更复杂的分块技术)。
速度不会快100(500K / 5K),但速度会明显加快。
答案 2 :(得分:0)
这是一个非常广泛的问题。我首先要弄清楚“插入”语句的瓶颈是什么。运行代码,并使用操作系统提供的任何内容来查看机器正在执行的操作。
如果瓶颈是CPU,您需要找到最慢的部分并加快速度。不太可能,给出了您的示例代码,但可能。
如果瓶颈是I / O或内存,那么你几乎肯定需要更好的硬件或基本的重新设计。
重新设计它的显而易见的方法是找到一种方法来处理50M记录中的增量。例如,如果您可以在记录更改时写入审计表,则您的cron作业可以查看该审计表并挑选自上次批处理运行以来修改过的任何数据。