在Symfony3中,我使用Doctrine的QueryBuilder从我的3500万行表中迭代多达500k行:
$query = $this->createQueryBuilder('l')
->where('l.foo = :foo')
->setParameter('foo', $foo)
->getQuery();
$results = $query->iterate();
foreach ($results as $result) {
$em->clear();
// My logic using $result[0]
}
在我开始迭代之前,这通常会接近512mb的内存使用量。还有什么方法可以优化这个吗?我是否正确阅读在迭代查询时关闭水合作用?
答案 0 :(得分:6)
generators我取得了很好的成绩。也许处理结果采用单独的方法可以帮助PHP清理未使用的对象。我不知道你在处理你的记录时做了什么,并且不能保证你会得到相同的结果,但在我的情况下,通过整个脚本执行,内存消耗保持不变:
public function getMyResults($foo)
{
$query = $this->createQueryBuilder('l')
->where('l.foo = :foo')
->setParameter('foo', $foo)
->getQuery();
foreach ($query->iterate() as $result) {
yield $result[0]
$em->clear();
}
}
public function processMyResults($foo)
{
foreach ($this->getMyResults($foo) as $result) {
}
}
如果这没有帮助,请考虑使用DBAL或PDO进行查询(两者都使用fetch()
方法,以避免一次性获取所有记录)。 Doctrine的迭代器可能会泄漏内存(PDO&#39结果集不应该)。
Doctrine将解决80%的问题。如果没有它,剩下的20%会更好。
在阅读迭代查询时关闭水合作用时,我是否正确?
不,除非你改变水合模式。您可以通过a second argument to the iterate()
method。