优化 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 列,因为这很慢。