Doctrine2 $ em->在foreach循环上持久化($ entity)

时间:2012-04-17 12:20:28

标签: symfony doctrine-orm

我目前在一个地方,我需要在foreach循环中创建或更新实体。

所以我正在做以下(短代码):

foreach ($dataset as $data) {
    $entity = new Entity();

    // ---- Some setting operations on the entity

    $em->persist($entity);
}

$em->flush();

我期待的是Doctrine管理实体,然后用一个语句将实体插入表中。

但是它发生了,Doctrine为每个创建的实体创建了一个语句。 由于$ dataset数组可能非常大(创建了很多实体),我希望将它打包成一个语句。

我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:17)

正如greg0ire所建议的,此链接描述了Doctrine如何优化INSERT语句:https://www.slideshare.net/jwage/doctrine-2-not-the-same-old-php-orm/47-sflive2010_Insert_Performance_Inserting_20(请参阅幻灯片#47)。它使用事务,但不在唯一语句中对相同对象的INSERT进行分组。

如果你真的需要一次划分传递给数据库服务器的数据量,我建议你每隔x语句处理一次EntityManager :: flush()。

答案 1 :(得分:14)

从Doctrine文档中,它说插入最好用批处理执行。它是@AlterPHP答案的发展。

您可以使用:

$batchSize = 20;

for ($i = 1; $i <= 10000; ++$i) {

    $car = new Car();
    // ... set number of wheels, but should always be to 4 right ?

    $em->persist($car);

    if (($i % $batchSize) === 0) {
        $em->flush();
        $em->clear(); // Detaches all objects from Doctrine!
    }
}

$em->flush(); // Persist objects that did not make up an entire batch
$em->clear();

PS:我刚从Doctrine 13.1. Bulk Inserts section读到。现在您只需要一个更大的停车位!

答案 2 :(得分:6)

更改此代码:

foreach ($dataset as $data) {
    $entity = new Entity();
    // ---- Some setting operations on the entity
    $em->persist($entity);
}

为:

foreach ($dataset as $data) {
    $entity = new Entity();
    // ---- Some setting operations on the entity
    $em->persist($entity);
    $em->flush();
    $em->clear();
}