【问题标题】:Split query with doctrine correctly正确使用教义拆分查询
【发布时间】:2016-10-18 17:01:30
【问题描述】:

我有一个教义查询,例如看起来像这样:

$object = $this->createQueryBuilder('object')
    ->leftJoin('object.element', 'element')->addSelect('element')
    ->leftJoin('object.element2', 'element2')->addSelect('element2')
    ->leftJoin('object.many', 'many')->addSelect('many')
    ->leftJoin('many.element3', 'element3')->addSelect('element3')
    ->leftJoin('many.element4', 'element4')->addSelect('element4')
    ->where('object.id = 1')
    ->getQuery()
    ->getSingleResult();

真正的查询有更多的连接,需要大量的内存,数据库性能不好。在本机 SQL 中,我会拆分它并正确加载它。我想要做的是加载第一个查询对象和一些基本的连接数据。这看起来像这样:

$object = $this->createQueryBuilder('object')
    ->leftJoin('object.element', 'element')->addSelect('element')
    ->leftJoin('object.element2', 'element2')->addSelect('element2')
    ->where('object.id = 1')
    ->getQuery()
    ->getSingleResult();

现在我还想加载manymany.element3many.element4。在单独的查询中。当我只使用教条延迟加载功能时,它会创建一个 SQL 查询 foreach 但我只希望它作为 1 个查询。

我知道可以在该关系上设置EAGER,但我只想为这个查询临时设置EAGER,并不总是在有人加入对象并访问它时。

【问题讨论】:

    标签: sql performance symfony doctrine-orm doctrine


    【解决方案1】:

    确实通过以下方式解决了我的问题:

    在我的对象中,我确实为集合添加了一个新的集合函数。

    /**
     * Set manies.
     */
    public function setManies($manies)
    {
        // this clear and foreach is needed to keep it as ArrayCollection so doctrine dont need for the unitofwork request the db again
        $this->manies->clear();
    
        foreach ($manies as $many) {
            $this->manies->add($many);
        }
    
        return $this;
    }
    

    在存储库中,我的代码如下所示:

    $object = $this->createQueryBuilder('object')
        ->leftJoin('object.element', 'element')->addSelect('element')
        ->leftJoin('object.element2', 'element2')->addSelect('element2')
        ->where('object.id = 1')
        ->getQuery()
        ->getSingleResult();
    
    $object->setManies($this->getEntityManager()->getRepository(Many::class)->loadByObjectId(
            $object->getId()
        ));
    
    return $object;
    

    这里是多个仓库中的函数

    // loadByObjectId in the many repository
    $manies = $this->createQueryBuilder('many')
        ->leftJoin('many.element3', 'element3')->addSelect('element3')
        ->leftJoin('many.element4', 'element4')->addSelect('element4')
        ->where('many.object = 1')
        ->getQuery()
        ->getResult();
    

    这样,SQL 被成功拆分为多个请求。在我的情况下,不是 1 个请求中的 60000 行,而是在 4 个请求中只影响了 40 行,这使得对象的水合速度更快。

    【讨论】:

      猜你喜欢
      • 2021-08-09
      • 2018-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多