Doctrine2 - 一次性多次插入

Mol*_*ain 26 php mysql symfony doctrine-orm

我是Doctrine的新手,对我来说还有一些模糊的区域.在这种情况下,我使用循环和实体管理器在数据库中插入新记录.它工作正常,但我注意到Doctrine按实体进行一次插入查询,这可能会变得非常庞大.

使用Doctrine2和Symfony 2.3,我想知道如何设置它,这样它只会产生一个带有所有值的插入查询(当然我们只讨论1个实体).

我的意思是改变这个:

INSERT INTO dummy_table VALUES (x1, y1)    
INSERT INTO dummy_table VALUES (x2, y2)
Run Code Online (Sandbox Code Playgroud)

INSERT INTO dummy_table VALUES (x1, y1), (x2, y2)
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

$em = $this->container->get('doctrine')->getManager();

foreach($items as $item){
    $newItem = new Product($item['datas']);
    $em->persist($newItem);
}

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

ukl*_*viu 45

根据这个答案,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();
Run Code Online (Sandbox Code Playgroud)

  • +1刷新剩余的对象......文档应该包含这个,就好像你的批量大小小于结果数没有任何反应 (3认同)
  • 请注意,`$em->clear()` 可能会对您未在函数中直接处理的其他实体产生错误的影响。例如,您可以获得与产品类别用户相关的一些异常...因此,仅清除您想要的类型的实体会更方便。在这种情况下,它将是`$em->clear('Product')` (3认同)