Doctrine2 Lazy vs Eager,或者为什么它会进行多次查询

时间:2015-01-28 10:36:51

标签: php mysql oop symfony doctrine-orm

所以我在我的一些项目中使用QueryBuilder,但是其他我需要创建RAW SQL查询以提高性能,因为我的关系有超过一百万行......

我发现QueryBuilder很糟糕的事实是,当你有关系时它会创建几个查询,例如,我有OneToManyProduct的{​​{1}}关系和一个{ {1}}在反面。{/ p>

我的查询有分页,因此仅限于Image。我的ManyToOne实体有大约270万行,这就是为什么我使用分页,执行这个简单的查询,提取LIMIT 10 OFFSET 0Image,因为我需要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爱好者。

1 个答案:

答案 0 :(得分:0)

你做过这样的事情:

SELECT i FROM AcmeBundle:Image i JOIN i.product p WHERE ...

这可以解释大量查询,因为Doctrine不会保留已提取的数据。

执行此类操作会让Doctrine实际保留ImageProduct的已提取数据:

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()