我有两个人:
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();
答案 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();