【问题标题】:How can I resolve this doctrine memory issue我该如何解决这个教义记忆问题
【发布时间】:2014-03-12 17:49:03
【问题描述】:

下面的代码遍历一个有大约 1,000,000 行的表。有人建议我使用 Doctrine 的 iterateResult() 方法来避免内存问题 (docs):

$batchSize = 1000;
    $i = 0;
    $q = $em->createQuery('SELECT i from MyBundle:Items i WHERE i.imgSize IS NULL');

    $results = array();

    $iterableResult = $q->iterate();
    while (($row = $iterableResult->next()) !== false) {

        $results[]=$row[0];
        $em->detach($row[0]);

        if (($i % $batchSize) === 0) {

            $em->clear(); // allegedly detaches all objects from Doctrine!
            $this->chunkedWhereCallback($results);

        }
        ++$i;
    }

即使我将批处理大小设置为 1,上面的代码也超出了允许的内存。如果我将查询更改为读取 SELECT i.id, i.img FROM MyBundle:Items i WHERE i.imgSize IS NULL,则内存错误不存在,但我的 $row 数组没有 [0] 键,例如:

array(1) {
  [5926] =>
  array(2) {
    'id' =>
    int(12794)
    'img' =>
    string(57) "http://some/url/1203/104962420.jpg"
  }
}

有人能告诉我我在这里缺少什么吗? Laravel 的 Eloquent 很好地处理了这个操作,但我想将代码移植到 Doctrine / Symfony2。我尝试将 php 内存限制设置为 1024M,这应该绰绰有余,而且比我在服务器上可用的还多。

Memory error is Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 32 bytes) in /Users/mre/Sites/ site/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php on line 699

【问题讨论】:

  • 也许您为所有 Doctrine 实体设置了急切加载并且该实体具有递归关系?
  • 或者它可以是一些递归操作,在你的$this->chunkedWhereCallback($results);中分配内存。为我们提供此方法的代码。
  • @MichaelSivolobov 没有定义实体关系。内存错误发生在任何其他代码运行之前。
  • 您的问题是$results[]=$row[0];。您保留对该数组中所有的迭代项的引用。这意味着 GarbageCollector 不能释放它们,因为它们属于数组。同时,detach()clear() 之类的操作将从EntityManager 中删除对项目的引用,但不是EM 阻止项目被gc'ed,而是$results[]

标签: php symfony doctrine-orm doctrine


【解决方案1】:

我也遇到了同样的问题,我不完全确定这是 Doctrine 的问题,似乎是 PHP 本身的问题。

无论如何,我找到的解决方案是强制 PHP 的垃圾收集像这样发生:

$batchSize = 1000;
$i = 0;
$q = $em->createQuery('SELECT i from MyBundle:Items i WHERE i.imgSize IS NULL');

$results = array();

$iterableResult = $q->iterate();
while (($row = $iterableResult->next()) !== false) {

    $results[]=$row[0];
    $em->detach($row[0]);

    if (($i % $batchSize) === 0) {

        $em->clear(); // allegedly detaches all objects from Doctrine!
        // Force PHP's GC
        gc_collect_cycles();
        $this->chunkedWhereCallback($results);

    }
    ++$i;
}

gc_collect_cycles 的调用应该释放内存并防止可用内存耗尽。

【讨论】:

  • 谢谢。我确实尝试过这个,并认为您可能还需要调用 gc_enable() 才能使其工作。无论如何,它似乎没有帮助。我以前遇到过教条的记忆问题——它在处理大量数据方面并不是很擅长。对我来说解决问题的是使用部分对象 doctrine-orm.readthedocs.org/en/latest/reference/… 感谢 IRC 上的一个人。
猜你喜欢
  • 1970-01-01
  • 2020-03-25
  • 2020-02-14
  • 2021-10-23
  • 1970-01-01
  • 2021-07-31
相关资源
最近更新 更多