优化 symfony2 代码,无需先搜索 ID
optimization in symfony2 code without having to search for ID first
我有一个名为 InstagramTag 的实体,它非常基础且简单:
class InstagramTag
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
* @ORM\Column(name="tag", type="string", nullable=true)
*/
protected $tag;
/**
*
* @ORM\OneToMany(targetEntity="App\MainBundle\Entity\InstagramPictureTag", mappedBy="tag")
*/
protected $picturetag;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get tag
*
* @return string
*/
public function getTag()
{
return $this->tag;
}
/**
* Set tag
*
* @param string $tag
* @return InstagramTag
*/
public function setTag( $tag)
{
$this->tag = $tag;
return $this;
}
}
我有这个例程,基本上检查带有特定标签的 InstagramTag 是否已经存在。如果不存在则创建一个,因此代码如下所示:
foreach ($image->tags as $tag) {
$existingTag = $this->em->getRepository('AppMainBundle:InstagramTag')->findOneByTag($tag);
$instaPictureTag = new InstagramPictureTag();
$instaPictureTag->setPicture($instaShopPicture);
if ($existingTag) {
$instaPictureTag->setTag($existingTag);
} else {
$instagramTag = new InstagramTag();
$instagramTag->setTag($tag);
$this->em->persist($instagramTag);
$instaPictureTag->setTag($instagramTag);
}
$this->em->persist($instaPictureTag);
}
代码相对较慢,因为 InstagramTag table 有 160 万个条目。因此,在 MySQL table.
上仅搜索 1 个标签大约需要 1.3 秒
看来 MySQL
是您的情况的瓶颈。所以我的建议是不要检查标签是否存在于 foreach
循环中,因为你查询 mySql
循环的每次迭代。
相反,我会创建 custom repository 方法,该方法将一次找到所有标签的实体(因此您只调用 mySQL
一次)
public function getRowsByTags(array $tags)
{
return $this->createQueryBuilder('i')
->andWhere('i.tag IN (:tags)')
->setParameter(':tags', $tags)
->getQuery()
->execute();
}
通过这种方式您可以获得 InstagramTag
个实体的集合。然后,在你的 foreach 循环中,你需要迭代这个集合(你在内存中迭代,而不触及你的慢 mysql),检查你的 InstagramTag
是否在那里。如果没有,您需要创建一个新的。
这里的其他问题是您是否在 mysql 中正确索引了 tag
列,因为这很慢。
我有一个名为 InstagramTag 的实体,它非常基础且简单:
class InstagramTag
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
* @ORM\Column(name="tag", type="string", nullable=true)
*/
protected $tag;
/**
*
* @ORM\OneToMany(targetEntity="App\MainBundle\Entity\InstagramPictureTag", mappedBy="tag")
*/
protected $picturetag;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get tag
*
* @return string
*/
public function getTag()
{
return $this->tag;
}
/**
* Set tag
*
* @param string $tag
* @return InstagramTag
*/
public function setTag( $tag)
{
$this->tag = $tag;
return $this;
}
}
我有这个例程,基本上检查带有特定标签的 InstagramTag 是否已经存在。如果不存在则创建一个,因此代码如下所示:
foreach ($image->tags as $tag) {
$existingTag = $this->em->getRepository('AppMainBundle:InstagramTag')->findOneByTag($tag);
$instaPictureTag = new InstagramPictureTag();
$instaPictureTag->setPicture($instaShopPicture);
if ($existingTag) {
$instaPictureTag->setTag($existingTag);
} else {
$instagramTag = new InstagramTag();
$instagramTag->setTag($tag);
$this->em->persist($instagramTag);
$instaPictureTag->setTag($instagramTag);
}
$this->em->persist($instaPictureTag);
}
代码相对较慢,因为 InstagramTag table 有 160 万个条目。因此,在 MySQL table.
上仅搜索 1 个标签大约需要 1.3 秒看来 MySQL
是您的情况的瓶颈。所以我的建议是不要检查标签是否存在于 foreach
循环中,因为你查询 mySql
循环的每次迭代。
相反,我会创建 custom repository 方法,该方法将一次找到所有标签的实体(因此您只调用 mySQL
一次)
public function getRowsByTags(array $tags)
{
return $this->createQueryBuilder('i')
->andWhere('i.tag IN (:tags)')
->setParameter(':tags', $tags)
->getQuery()
->execute();
}
通过这种方式您可以获得 InstagramTag
个实体的集合。然后,在你的 foreach 循环中,你需要迭代这个集合(你在内存中迭代,而不触及你的慢 mysql),检查你的 InstagramTag
是否在那里。如果没有,您需要创建一个新的。
这里的其他问题是您是否在 mysql 中正确索引了 tag
列,因为这很慢。