Doctrine ORM内存不足,PHP Symfony

3
我正在运行以下脚本来从我的数据库中选择用户列表并将其传递给我的服务。
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb
        -> select('s')
        -> from('AppBundle\Entity\SubscriberDetails', 's')
        -> where($qb->expr()->not($qb->expr()->exists($qb1->getDQL())))
        -> setMaxResults($numcampaigns)
    ;
    $subscribers = $qb->getQuery()->getResult();

WHERE

    $qb1 = $this->getEntityManager()->createQueryBuilder();
    $qb1
        ->select('send')
        ->from('AppBundle\Entity\Subscribers', 'send')
        ->where('DATE_FORMAT(now(), \'%e-%b-%Y\') - DATE_FORMAT(FROM_UNIXTIME(send.last_campaign), \'%e-%b-%Y\') <=360')
        ->andwhere('send.bounced <> 1')
        ->andwhere('send.complaint <> 1')
        ->andwhere('s.emailaddress = send.emailaddress');

以下脚本适用于3万个用户,而我正试图将其扩展到30万个用户的选择。在运行30万个用户时,我会遇到以下错误:

6.0662  132446208  15. Doctrine\ORM\Internal\Hydration\ObjectHydrator->hydrateRowData()/Applications/MAMP/htdocs/mediaff/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php:165
6.0663  132448496  16. Doctrine\ORM\Internal\Hydration\ObjectHydrator->getEntity()/Applications/MAMP/htdocs/mediaff/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php:494
6.0663  132448496  17. Doctrine\ORM\UnitOfWork->createEntity() /Applications/MAMP/htdocs/mediaff/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php:273
6.0663  132449488  18. ReflectionProperty->setValue() /Applications/MAMP/htdocs/mediaff/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2586
6.0781  132445688  19. Symfony\Component\Debug\ErrorHandler::handleFatalError()/Applications/MAMP/htdocs/mediaff/vendor/symfony/symfony/src/Symfony/Component/Debug/ErrorHandler.php:0
6.0782  132434104  20. spl_autoload_call() /Applications/MAMP/htdocs/mediaff/vendor/symfony/symfony/src/Symfony/Component/Debug/ErrorHandler.php:613
6.0782  132434264  21. Symfony\Component\Debug\DebugClassLoader->loadClass()/Applications/MAMP/htdocs/mediaff/vendor/symfony/symfony/src/Symfony/Component/Debug/ErrorHandler.php:613

我认为第二列是内存使用情况。你有什么想法,如何解决这个问题?非常感谢您的帮助。


1
如果您不想得到一个“只需增加memory_limit”的答案,让我们从“为什么首先需要选择300k个用户?”开始。 - Federkun
绝对不是那种“内存增加”的人!这些被选中进行进一步处理,例如映射其他详细信息,通过API发送处理后的信息给合作伙伴,接收和解析响应等。 - Sky21.86
ORM(甚至是php)并非针对大规模批处理操作而设计。有几十个与此完全相同主题的其他软件问题。你可以使用$em->clear()和其他一些技巧来解决一些问题,但实际上在一个批次中处理30万个用户?不可能的事情。很惊讶您甚至可以使30k的工作正常运行。 - Cerad
正如@Cerad所说,一次性有300k个用户可能不太可能发生。假设128mb的内存限制,每个用户大约只剩下447字节。由于存在一些开销(例如像doctrine、symfony这样的框架(例如您的控制器和服务)等),您可以从中减去相当大的一部分。因此,实际数据留给您的空间真的不多。考虑到每个用户的用户名/名字/姓氏需要20-50字节,相关实体(例如地址,也可能需要100字节),您将无法使用该内存。 - ccKep
1
批处理,是的 - Doctrine实际上有一篇关于此的文章。特别是请参阅最后一部分。请查看:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/batch-processing.html#iterating-large-results-for-data-processing - ccKep
显示剩余2条评论
1个回答

2
如果您的数据处理允许,您可以使用分页器并遍历页面,在每次迭代中调用em->clear(),以便保持内存消耗恒定。

1
这就是我最终所做的!此外,每次迭代后我添加了 em ->getConnection()->close(),因为我的数据库由于“连接过多”而开始崩溃。 - Sky21.86

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接