使用学说2忽略批处理插入物的最有效方法



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

目前在做:

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
    }
}

但是这样做是非常耗时的,有1000个条目,脚本有时需要超过10分钟的时间才能完成。我已经看到其他帖子建议在这样的批处理处理时,每20个左右都会冲洗一次问题,这是如果这20个是重复的,那么整个交易就会消失,我不确定我将如何返回并尝试并尝试和尝试在再次重新提交之前,找到排除它的有问题的条目。

对此的任何帮助将不胜感激。

您可以做一个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());
} 

相关内容

  • 没有找到相关文章

最新更新