【发布时间】:2016-01-30 08:31:04
【问题描述】:
我正在尝试使用 Doctrine2 和 Symfony2 夹具包在 MySQL 数据库中插入大量数据(超过 30 000 行)。
我看了the right way to do it。我看到了很多关于内存泄漏和 Doctrine 的问题,但没有让我满意的答案。它通常带有 Doctrine clear() 函数。
所以,我做了各种不同的形状:
while (($data = getData()) {
$iteration++;
$obj = new EntityObject();
$obj->setName('henry');
// Fill object...
$manager->persist($obj);
if ($iteration % 500 == 0) {
$manager->flush();
$manager->clear();
// Also tried some sort of:
// $manager->clear($obj);
// $manager->detach($obj);
// gc_collect_cycles();
}
}
在flush() 之后(我很确定),PHP 内存仍然疯狂。实际上,每次刷新实体时,内存都会根据批次大小和实体增加一定量,直到达到致命的Allowed Memory size exhausted错误。对于一个非常非常小的实体,它可以工作,但内存消耗增加太多:几 MB,而应该是 KB。
clear()、detach() 或者调用 GC 似乎根本没有效果。它只会清除一些 KB。
我的方法有缺陷吗?我在某个地方错过了什么吗?是bug吗?
更多信息:
- 没有
flush(),内存几乎不会移动; - 降低批次不会改变结果;
- 数据来自需要清理的 CSV;
编辑(部分解决方案):
@qooplmao 带来了显着减少内存消耗的解决方案,禁用学说 sql logger:$manager->getConnection()->getConfiguration()->setSQLLogger(null);
但是,它仍然异常高并且还在增加。
【问题讨论】:
-
您是否尝试降低批量大小(500)?它会更慢,但内存占用更少
-
是的。我尝试降低它(100、20、1)并增加它(1000、2000、5000),没有变化。
-
这里只是好奇,getData() 返回什么?它从哪里获取信息?多少钱?与文档相比,循环的选择很有趣,我很喜欢
-
你是在开发中做这个吗?如果是这样,您最好禁用 SQL 记录器 (
$manager->getConnection()->getConfiguration()->setSQLLogger(null))。 -
@Gui-Don,你能试试这个吗? coderwall.com/p/awzjhw/…
标签: php symfony memory doctrine-orm