所以我在我的一些项目中使用QueryBuilder,但是其他我需要创建RAW SQL查询以提高性能,因为我的关系有超过一百万行......
我发现QueryBuilder很糟糕的事实是,当你有关系时它会创建几个查询,例如,我有OneToMany
到Product
的{{1}}关系和一个{ {1}}在反面。{/ p>
我的查询有分页,因此仅限于Image
。我的ManyToOne
实体有大约270万行,这就是为什么我使用分页,执行这个简单的查询,提取LIMIT 10 OFFSET 0
加Image
,因为我需要Image i
对于我的10张图片,我最终得到1个查询,Product p
的每个p.title
收到10个查询。
这是不必要的,只需2个查询,一个用于Product
,一个用于Image
,使用Image
即可获得。但我需要将Product
置于fetch="EAGER"
映射中,否则我将再次获得11个查询..
只有10张图片并不难,但是当用户过滤500张图片时,响应时间会越来越高......这就是为什么我最终会进行RAW查询,性能最佳,没有额外的查询(只有1个包含所有内容的查询)但是无法使用像QueryBuilder那样的对象,无法访问twig内的fetch="EXTRA_LAZY"
来获取标题,而是我需要{{1}并致电Product
等
所以我需要知道为什么QueryBuilder在阅读时会那么简单但是在持久化对象时非常精彩(简单,快速,干净......)以及如何在不失去性能的情况下使用QueryBuilder与大型DB一起工作并且没有得到大量额外的不必要的查询。
一个示例查询,就是这个
image.product.title
使用SELECT p.title AS product_title
似乎只使用一个查询,它可运行的原始内容具有INNER JOIN(实际上它是如何在不使用image.product_title
的情况下工作)但性能仍然存在低于执行RAW SQL查询...对于10.000行查询,RAW SQL = 500MS,使用QB它的1,100 MS。我知道我不会使用10,000行,但有机会...
问题仍然是相同的,除了对象操作之外,RAW SQL还有哪些优点和缺点。何时使用LAZY或EAGER以及为什么/为什么/何时不需要它们。
所有这一切可能会在我的DevTeam中结束一次讨论。因为我是QB爱好者。
答案 0 :(得分:0)
你做过这样的事情:
SELECT i FROM AcmeBundle:Image i JOIN i.product p WHERE ...
这可以解释大量查询,因为Doctrine
不会保留已提取的数据。
执行此类操作会让Doctrine
实际保留Image
和Product
的已提取数据:
SELECT i, p FROM AcmeBundle:Image i JOIN i.product p WHERE ...
然后,您既不需要EAGER
也不需要EAGER_LAZY
。
我可能错过了你问题的重点。如果我有,请纠正我,我可能会提出其他建议。
$qb = $this->createQueryBuilder('i');
$qb->innerJoin('i.product', 'p');
$qb->addSelect('p'); // Very importang, hints Doctrine to preserve fetched Product
$qb->where('i.X = Y');
return $qb->getQuery()->getResult()
或使用PARTIAL
:
$qb = $this->createQueryBuilder('i');
$qb->innerJoin('i.product', 'p');
$qb->select('PARTIAL i.{image_field1, image_field2}', 'PARTIAL p.{product_field1, product_field2}'); // Very importang, hints Doctrine to preserve fetched Product
$qb->where('i.X = Y');
return $qb->getQuery()->getResult()