2015-06-17 94 views
1

我需要編寫一個foreach循環,其中用戶被訂閱並使用doctrine插入到數據庫中。我的代碼:Symfony,創建新對象很慢

$i=0; 
$batchSize=20; 

foreach ($members as $member) { 
    $subscription = new Subscription($company, $user); 
    $entityManager->persist($subscription); 
    // debug 
    $i++; 
    error_log($i); 

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

這段代碼真的很慢。對於大約100個用戶,這段代碼需要幾分鐘才能執行。這應該快很多吧?

當我刪除對象創建(和setMember,和entityManager線)時,此代碼執行不到一秒鐘。

我在做什麼錯?

更新:實體代碼 我改變了一些變量,因爲代碼祕密。如果任何代碼錯誤,那是因爲我做了很快的修改,所以我可以在這裏發佈我的問題。在上面的訂閱類使用

class Subscription implements \JsonSerializable 
{ 

    protected $id; 
    protected $company; 
    protected $user; 
    private $created_on; 
    private $blocked; 
    private $attributes; 

    public function __construct(Company $company, User $user) 
    { 
     $this->company = $company; 
     $this->user = $user; 
     $this->created_on = new \DateTime(); 
     $this->blocked = false; 

     $this->attributes = new AttributeCollection(); 

     $this->setDefaultAttributes(); 
    } 

    public function jsonSerialize() { 
     return array(
      'id' => $this->id, 
      'user' => $this->user, 
      'blocked' => $this->blocked, 
      'created_on' => $this->created_on->format('Y-m-d H:i:s') 
     ); 
    } 
    // due to company secrets variables have been changed to a,b,c,d,e,f 
    public function setDefaultAttributes() 
    { 
     if (null == $this->attributes) 
      $this->attributes = new AttributeCollection(); 
     $this->attributes->addAttribute(new Attribute('a')); 
     $this->attributes->addAttribute(new Attribute('b')); 
     $this->attributes->addAttribute(new Attribute('c')); 
     $this->attributes->addAttribute(new Attribute('d')); 
     $this->attributes->addAttribute(new Attribute('e')); 
     $this->attributes->addAttribute(new Attribute('f')); 
    } 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function setUser(User $user = null) 
    { 
     $this->user = $user; 

     return $this; 
    } 

    public function getUser() 
    { 
     return $this->user; 
    } 

    public function setCompany(Company $company = null) 
    { 
     $this->company = $company; 
     return $this; 
    } 

    public function getCompany() 
    { 
     return $this->company; 
    } 

    public function getCreatedOn() 
    { 
     return $this->created_on; 
    } 

    public function setBlocked($blocked) 
    { 
     $this->blocked = $blocked; 

     return $this; 
    } 

    public function getBlocked() 
    { 
     return $this->blocked; 
    } 

    public function setAttributes(AttributeCollection $attributes = null) 
    { 
     $this->attributes = $attributes; 
     return $this; 
    } 

    public function getAttributes() 
    { 
     return $this->attributes; 
    } 

} 

AttributeCollection類:

class AttributeCollection 
{ 

    protected $id; 
    protected $attributes; 

    public function __construct() 
    { 
     $this->attributes = new ArrayCollection(); 
    } 

    public function removeDefaults() 
    { 
     foreach ($this->attributes as $attribute) 
      if ($attribute->isSystemDefault()) 
       $this->removeAttribute($attribute); 
    } 

    public function clearDefaults() 
    { 
     foreach ($this->attributes as $attribute) 
      $attribute->setSystemDefault(false); 
    } 

    public function getAttributes() 
    { 
     return $this->attributes; 
    } 

    public function addAttribute(Attribute $attribute) 
    { 
     if (!$this->findAttributeByName($attribute->getName())) 
      $this->attributes[] = $attribute; 
    } 

    public function removeAttribute(Attribute $attribute) 
    { 
     $this->attributes->removeElement($attribute); 
    } 

    public function findAttributeByName($name) 
    { 
     foreach ($this->attributes as $attribute) 
      if ($attribute->getName() == $name) 
       return $attribute; 
     return; 
    } 

    public function get($name) 
    { 
     $attribute = $this->findAttributeByName($name); 
     if ($attribute) 
      return $attribute->getValue(); 
     return; 
    } 

    public function getAll() 
    { 
     return $this->attributes->toArray(); 
    } 

} 
+0

也許刷新'20'實體是一項耗時的工作。你試過降低'$ batchSize'嗎? – D4V1D

+0

@ D4V1D我現在知道這是耗時的模型創建。如果我刪除原則相關的行,並離開模型創建。它需要同樣長的時間。 –

+0

這行'error_log($ i);'做了什麼?我的意思是它使用哪個處理程序?它每次都打開/關閉日誌文件嗎? –

回答

1

事實證明,通過構造函數傳遞這些模型導致了問題。

我改變了我的代碼:

class Subscription { 
    ... 
    public function __construct($Company == null, $member == null) { 
     ... 
    } 
} 

,並在我的foreach循環:

$subscription = new Subscription(); 
$subscription->setCompany($company); 
$subscription->setMember($member); 

這樣一切都運行流暢,並如預期。我不知道爲什麼構造函數會放慢一切。但顯然它確實如此。

0

它不是最佳的使用這樣的小$batchSize對於這樣小的實體。

這種持久性的方式在文檔中作爲如何優化內存和連接加載的示例,而不是整個腳本的速度。

如果您在$i$batchSize上刪除這些檢查,速度會更快。

foreach ($members as $member) { 
    $subscription = new Subscription(); 
    $subscription->setMember($member); 
    $entityManager->persist($subscription); 
} 
$entityManager->flush(); 

也請記住,在DEV-ENV你有debug選項設置爲enabled,所有查詢到DB在文件中記錄。這也浪費時間。

+0

「當我刪除對象創建(以及setMember和entityManager行)時,此代碼執行時間不到一秒。」 $ i + $ batchSize檢查不是我的問題 –

+0

不是檢查。我的意思是'$ entityManager-> flush();'和'$ entityManager-> clear();'如果在所有操作之後只有一次刷新,它會更快。 –

+0

這些沖洗和清除不是問題。我刪除了這些,只留下模型創建。看來,模型的創建需要很長時間。 –