我需要编写一个foreach循环,用户可以使用doctrine订阅并插入到数据库中。我的代码:
$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;
}
}
上面的Subscription类中使用的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 :(得分:1)
事实证明,通过构造函数传递这些模型会导致问题。
我改变了我的代码:
class Subscription {
...
public function __construct($Company == null, $member == null) {
...
}
}
在我的foreach循环中:
$subscription = new Subscription();
$subscription->setCompany($company);
$subscription->setMember($member);
这样一切都顺利进行并且符合预期。我不知道为什么构造函数会减慢一切。但显然确实如此。
答案 1 :(得分:0)
对这样的小实体使用这么小的$batchSize
是不理想的。
这种持久性的方式在文档中提供,作为如何优化内存和连接加载的示例,而不是整个脚本的速度。
如果您在$i
和$batchSize
上删除这些检查,则会更快。
foreach ($members as $member) {
$subscription = new Subscription();
$subscription->setMember($member);
$entityManager->persist($subscription);
}
$entityManager->flush();
另请注意,在dev-env中,debug
选项设置为enabled
,并且对数据库的所有查询都记录在文件中。这也浪费时间。