我正在做一个导入模块,批量插入90000个寄存器和symfony / doctrine。为了插入每个对象,我必须从其他表中读取一个字段。 因此,对于每个寄存器,我首先从另一个表中获取相关对象,如下所示:
$this->doctrine->getRepository('table1')
把它放在我想写的新对象中,然后写出来,就像这样:
$em = $this->doctrine->getManager();
$em->merge($newObject);
$em->flush();
(我使用merge,因为它是保存现有和新对象的一般方法) 但即使我设置apache进行漫长的等待(这是不可取的),这需要花费太多时间和响应超时。 Doctrine_Collection方法也不起作用。 任何人都知道一种更好的方法,以便在合理的时间内返回吗?
由于
答案 0 :(得分:3)
Doctrine将在身份映射中保存所有托管实体实例(UnitOfWork
) - 这意味着任何计划保留(在flush()
上)的实体都将保留在内存中。如果您执行大量插入操作,这可能会成为性能杀手。
相反,持久/保存一个实例然后每次调用flush将导致每个实体至少有一个INSERT/UPDATE
- 由于不需要的数据库查询,这将再次影响性能。
您应该考虑将所需的插入分解为较小的块,并允许实体管理器释放任何内存实例:
foreach($entities as $index => $entity) {
$entity->setFoo('bar');
$objectManager->merge($entity);
if (($index % 1000) == 0) {
$entityManager->flush(); // Flush the changes every 1000 iterations
$entityManager->clear(); // Clear all managed entities
}
}
您提到的Doctrine_Collection
实际上适用于Doctrine 1
,并且从那时起已经发生了很多变化。
您应该查看Doctrine 2 documentation on batch processing以获取更多信息。