2

我正在做一个导入模块,它使用 symfony/doctrine 批量插入 90000+ 个寄存器。为了插入每个对象,我必须从其他表中读取一个字段。因此,对于每个寄存器,我首先从另一个表中获取相关对象,如下所示:

$this->doctrine->getRepository('table1')

放到我要写的新对象里面,然后写,像这样:

$em = $this->doctrine->getManager();
$em->merge($newObject);
$em->flush();

(我使用合并,因为它是保存现有对象和新对象的通用方法)但是即使我将 apache 设置为长时间等待(这是不可取的),这也会花费太多时间并且响应超时。Doctrine_Collection 方法也不起作用。任何人都知道一种方法可以更好地做到这一点,以便在合理的时间内返回?

谢谢

4

1 回答 1

3

Doctrine 将在一个身份映射 (the) 中保存所有托管实体实例UnitOfWork- 这意味着任何计划持久化 (on 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 文档以获取更多信息。

于 2013-11-04T13:20:51.147 回答