Doctrine结合JoinTable插入

时间:2017-05-30 09:42:32

标签: php symfony doctrine-orm doctrine

我有两个人:

Voucher
Support

这些实体有一个名为

的连接表
 voucher_support

当我向新凭证添加1000个现有支持时,它会在voucher_support上调用1000个INSERT查询到我的SQL服务器。当然还有50.000也有50.000个插页。

我如何才能实现该原则只需进行一次INSERT并提高我的表现?

编辑

我认为批量插入不是解决方案。 以下是我目前的代码,以便更好地理解:

$voucher = new Voucher();
$voucher->setCreatedAt(new \DateTime());
$supports = $this->em->getRepository('Support')->getOpen();
foreach($supports as $support){
    // this generates for each support a INSERT in join table.
    $voucher->addSupport($support);
}
$this->em->persist($voucher);
$this->em->flush();

2 个答案:

答案 0 :(得分:0)

阅读Doctrine2文档的Bulk inserts部分。它建议对每个“批次”使用flush()。 您还应该考虑使用事务包装它。

<?php
$batchSize = 20;
for ($i = 1; $i <= 10000; ++$i) {
    $user = new CmsUser;
    $user->setStatus('user');
    $user->setUsername('user' . $i);
    $user->setName('Mr.Smith-' . $i);
    $em->persist($user);
    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();

答案 1 :(得分:-1)

Doctrine2不允许您将多个INSERT语句合并为一个:

有些人似乎想知道为什么Doctrine不使用多插入(插入(...)值(...),(...),(...),...

首先,只有mysql和更新的postgresql版本支持此语法。其次,当使用AUTO_INCREMENT或SERIAL并且ORM需要用于对象的身份管理的标识符时,没有简单的方法来获得这样的多插入中的所有生成的标识符。最后,插入性能很少是ORM的瓶颈。普通插入对于大多数情况来说足够快,如果你真的想做快速批量插入,那么多插入并不是最好的方法,即Postgres COPY或Mysql LOAD DATA INFILE要快几个数量级。

这就是为什么不值得努力实现在ORM中对mysql和postgresql执行多插入的抽象的原因。 您可以在此处阅读有关Doctrine2批处理的更多信息:http://www.doctrine-project.org/blog/doctrine2-batch-processing.html

您可以切换到DBAL或通过在设定数量的插入后刷新实体管理器来小批量处理数据:

$batchSize = 20;

foreach ($items as $i => $item) {
     $product = new Product($item['datas']);

     $em->persist($product);

     // flush everything to the database every 20 inserts
     if (($i % $batchSize) == 0) {
         $em->flush();
         $em->clear();
    }
}

// flush the remaining objects
$em->flush();
$em->clear();