使用 CakePHP 的 saveMany() 保存 >10000 条记录

Posted

技术标签:

【中文标题】使用 CakePHP 的 saveMany() 保存 >10000 条记录【英文标题】:Save >10000 records with CakePHP's saveMany() 【发布时间】:2012-03-04 12:05:33 【问题描述】:

我正在尝试使用 Cakephp 2.1 的方法 saveMany() 保存超过 10000 条记录的列表。但它给了我一个 500 错误,或者一个“内存耗尽”的致命错误。

如果我在处理完整个数组后对其进行调试(因此,不调用 save 方法),时间在 0.05 秒以下。但是当我添加保存方法($this->saveMany($save, array('validate' => false));)时,它向我显示了上述错误之一。

我提到我在 mysql 中使用 InnoDB 作为存储引擎,使用 PHP 作为脚本语言。

我做错了什么,我该如何解决?

编辑

我回到这个问题,因为我“解决了”为什么大量记录无法保存。原因是……好吧,甚至一条记录都没有保存。我测试了只保存生成的数组中的第一个元素,这就是它发生的情况:它增加内存直到限制,然后它死了。我已经把它放在我的本地主机上,有 2GB 的内存,它仍然给我超出内存的错误。这很奇怪,我不明白为什么会这样。应用于另一个模型的相同代码按预期工作。我重新创建了模型及其表,但没有成功。我能想到的唯一原因是表名的长度,但这对我来说毫无意义。仅仅为了保存一条记录,什么会导致内存增加?

【问题讨论】:

您需要多久执行一次此操作? 10000 条记录从何而来?您需要提供更多信息,以便人们提出替代方法。 我正在为我的应用程序构建一个缓存,这样每当我需要检索和计算一些数据时,我只需要从这 10000 条记录中获取几条记录。我只会这样做几个次,手动。所以脚本的唯一要求是实际工作。 更新了我的答案。您可以访问 MySQL 控制台吗? 这很奇怪。您应该注释掉模型中的所有验证规则,以确保它们不会以任何方式影响。也尝试使用较小的结果集,如 10 行。将 debug 设置为 2 看看 sql dump 是否有什么奇怪的地方。 我解决了这个问题。我正在覆盖 Cake 方法并导致无限循环。很傻。感谢您的所有帮助,将您的答案标记为已接受:) 【参考方案1】:

保存 10000 行可能需要一段时间。确保你已经将php的时间限制set_time_limit(120);设置得足够大。

您也可以尝试像这样一一保存记录:

foreach($save as $s)

    $this->create();
    $this->save($s, array('validate' => false));


编辑 1:

但如果原始数据来自数据库,您可以使用 MySQL 控制台或使用 $this->query(); 将其直接复制到缓存表中

或者你可以SELECTINTO OUTFILELOAD DATA INFILE它到缓存表。

编辑 2:

然后我想到的唯一一件事就是将数据保存到磁盘上的文本文件中,然后在另一个函数中读取它,然后在时间/内存限制允许的时间保存尽可能多的行。您也可以尝试将其保存在 csv 文件中并使用 $this->query('LOAD DATA LOCAL INFILE xxx ...');

我想到你应该在保存之前禁用索引以使它们更快。你可以使用$this->query('ALTER TABLE table DISABLE KEYS;');来做到这一点

【讨论】:

它仍然没有走到最后。它再次发出内存超出错误。我无法更改内存/时间限制,因为我在付费主机上。 我无权访问控制台,也无法完全复制它,因为我需要对表中的数据执行一些操作。只有在修改数据以进行缓存后,才应保存它。

以上是关于使用 CakePHP 的 saveMany() 保存 >10000 条记录的主要内容,如果未能解决你的问题,请参考以下文章

cakephp saveMany 使用 $fieldList (无表单)

cakePHP saveMany 不工作

CakePHP - 当某些字段为空时,防止模型数据保存在 saveMany 调用中

saveMany 验证无法正常工作

验证不适用于 saveMany

Cakephp 多个输入字段