最有效的方法是使用doctrine 2批量INSERT IGNORE

Cha*_*ase 6 php mysql symfony doctrine-orm

我有一个脚本,需要获取数据库中的条目列表,然后迭代那些在另一个表中创建新条目,如果它们不存在.

目前正在做:

foreach($entries as $entry){
    $newItem = new Item();
    $newItem->setAttribute($entry->getAttribute());
    $entityManager->persist($newItem);
    try{
        $entityManager->flush();
    } catch(\Exception $e){
        if(!strpos($e->getMessage(),'Duplicate')){
            throw $e;
        }
        $entityManager = $this->getDoctrine()->getManager(); 
        //refreshes the entity manager
    }

}
Run Code Online (Sandbox Code Playgroud)

但是这样做是非常耗时的,有1000个条目,脚本有时需要10分钟才能完成.我已经看到其他帖子建议在进行这样的批量处理时每隔20个左右记录一次,如果这20个记录中有一个是重复的,那么整个事务就会死掉,我不知道怎么回去试试看找到有问题的条目以在再次重新提交之前将其排除.

任何有关这方面的帮助将不胜感激.

b.b*_*4rd 4

您可以执行一项操作SELECT来获取数据库中已存在的记录,然后跳过这些记录。此外,尝试只执行flush()一次clear()或调整批量大小。我还建议使用事务(如果你使用 InnoDB)。

$this->_em->getConnection()
    ->beginTransaction();

try {
    $created = array(/* all primary keys that already exist */);
    $i = 1;
    $batchSize = sizeof($entries);
    foreach ($entries as $entry) {

        if (in_array($entry->getMyPrimaryKey(), $created)) {
            continue;
        }

        $newItem = new Item();
        $newItem->setAttribute($entry->getAttribute());
        $entityManager->persist($newItem);

        if (($i % $batchSize) == 0) {
            $this->_em->flush();
            $this->_em->clear();
        }

        $i++;
    }

    $this->_em->getConnection()
        ->commit();
} catch (\Exception $e) {
    $this->_em->getConnection()
        ->rollback();
    $this->_em->close();

    throw new \RuntimeException($e->getMessage());
} 
Run Code Online (Sandbox Code Playgroud)