2017-05-03 81 views
1

我创建了一个symfony命令,该命令应该导入2M条目并将它们插入到数据库中。Symfony3/Doctrine 2刷新错误

我把一个刷新/清除,并产生每500个条目,使其有可能插入它的教义和跟踪插入的进展。在我的机器有它的工作原理MySQL数据库服务器,而在PostgreSQL远程服务器不工作时,我得到的通知:

[Symfony\Component\Debug\Exception\ContextErrorException] 
    Notice: Undefined index: 0000000025969b1e00000000029e7855 

Exception trace: 
() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2917 
Doctrine\ORM\UnitOfWork->getEntityIdentifier() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:656 
Doctrine\ORM\Persisters\Entity\BasicEntityPersister->prepareUpdateData() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:692 
Doctrine\ORM\Persisters\Entity\BasicEntityPersister->prepareInsertData() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:271 
Doctrine\ORM\Persisters\Entity\BasicEntityPersister->executeInserts() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1014 
Doctrine\ORM\UnitOfWork->executeInserts() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:378 
Doctrine\ORM\UnitOfWork->commit() at /var/nginx/kweeri-next/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:356 
Doctrine\ORM\EntityManager->flush() at /var/nginx/kweeri-next/var/cache/dev/appDevDebugProjectContainer.php:6083 
DoctrineORMEntityManager_00000000612352fa000000006464aa610448bf5c446411a05ad87329e18cead6->flush() at /var/nginx/kweeri-next/src/AppBundle/Utility/Clients/IRI/PPS/ImportItems.php:219 

这就是冲水把通知的代码。

public function importDictionnary($companyMachineName, $file) { 
     $company = $this->em->getRepository("AGAdminBundle:Company")->findOneBy(["machineName" => $companyMachineName]); 
     if (!$company) { 
      throw new EntityNotFoundException("no company found for $companyMachineName"); 
     } 
     $eans = $file; 
     $this->logger->addInfo("File downloaded"); 

     $product_repo = $this->em->getRepository(\AppBundle\Entity\PPS\Product::class); 
     $existings = array_map(function (\AppBundle\Entity\PPS\Product $product) { 
      return $product->getEan(); 
     }, $product_repo->findBy(["company" => $company])); 
     $old_value = -1; 
     foreach ($eans as $k => $ean) { 
      if (!in_array($ean, $existings)) { 
       $this->em->persist(new \AppBundle\Entity\PPS\Product($ean, $company)); 

       if ($k % 500 == 0) { 
        yield round(($k/count($eans)) * 100); 
        $this->em->flush(); 
        $this->em->clear(); 
       } 
      } 
     } 
     $this->em->flush(); 
    } 

编辑: 它需要角落找寻30秒得到2-我的机器上。在遥远的机器上,它需要20分钟才能产生2并停止。

+1

不像我应该那样熟悉产量。每500个循环之后,$公司是否被重新加载?当然,如果没有,那么mysql版本也会失败。 – Cerad

+0

@Cerad我通过保留companyId来解决这个问题,然后只重新载入回复中建议的引用。但仍然很慢: mySQL上2小时,PostgreSQL上11小时。 – d3cima

+0

关于加快进口,有几百个问题。但没有魔力。使用ORM会增加一些不重要的开销。放弃DBAL将有很大帮助,但是无论做什么,做150万件事情都会变得缓慢。 – Cerad

回答

2

当您拨打$em->clear()时,整个身份图将被清除。您需要重新加载数据库中的所有对象才能使用它们,否则教义无法在标识映射中找到导致未定义索引错误的对象。

如果您知道对象ID并且您不需要使用对象属性,则可以使用引用而不是从数据库加载对象。

+0

我尝试了一下我公司的参考,它可以工作,但它速度很慢。 mySQL上的1500000 forh和Postgresql的11h。 – d3cima

+0

你可以监控SQL查询吗?我想你正在做一个循环内的SELECT(你可能会意外地通过延迟加载)。 – kormik