在foreach循环中Doctrine2 $ em-> persist($ entity)

Joh*_*auß 28 symfony doctrine-orm

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

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

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

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

    $em->persist($entity);
}

$em->flush();
Run Code Online (Sandbox Code Playgroud)

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

但它发生了,Doctrine为每个创建的实体创建了一个语句.由于$ dataset数组可能相当大(创建了很多实体),我想把它打包成一个语句.

我怎样才能做到这一点?

Alt*_*PHP 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().


Rom*_*ert 16

从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);
Run Code Online (Sandbox Code Playgroud)

PS:我刚从Doctrine 13.1中读过.批量插入部分.现在你所需要的只是一个更大的停车位!

  • $ em-> clear()表示以前连接到实体管理器的所有实体现在都已分离.它有助于防止内存泄漏,但另一方面,您无法对实体执行进一步的持久性/更新操作,因为它们现在不受实体管理器的管理. (4认同)

小智 6

更改此代码:

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

至:

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

  • 这显然迫使每个声明插入一个插入.我以为会有一种方法可以插入一个语句. (7认同)
  • 不能同意这个解决方案,伙计们。在循环中每次都调用 `flush()` 不是一个好主意。如果需要循环的数据足够大,则会极大地降低性能。 (2认同)