31

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

所以我正在执行以下操作(短代码):

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

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

    $em->persist($entity);
}

$em->flush();

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

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

我怎样才能做到这一点?

4

3 回答 3

22

从 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(Car::class); // Detaches all Car objects from Doctrine!
    }
}

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

PS:我刚从Doctrine 13.1 中读到。批量插入部分。现在您只需要一个更大的停车场!

于 2015-05-08T15:23:24.187 回答
19

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

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

于 2012-04-17T14:20:50.890 回答
4

更改此代码:

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();
}
于 2012-06-06T02:04:58.527 回答