2017-05-03 124 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