2015-06-17 93 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

这些冲洗和清除不是问题。我删除了这些,只留下模型创建。看来,模型的创建需要很长时间。 –