lcp*_*lcp 5 eager-loading symfony doctrine-orm
使用 Symfony 3.2 和 Doctrine 2.5,我很难理解 fetch "EAGER" 在多对多和多对一关系中应该如何工作。
假设我们有两个实体,用户和站点,以及一个多对多关联:
class User
{
/**
* @ORM\ManyToMany(targetEntity="Site", inversedBy="users", fetch="EAGER")
* @ORM\JoinTable(name="user_site")
*/
private $sites;
}
class Site
{
/**
* @ORM\ManyToMany(targetEntity="User", mappedBy="sites")
*/
private $users;
}
Run Code Online (Sandbox Code Playgroud)
在我的控制器中,我只需调用
$users = $this->getDoctrine()->getRepository('CoreBundle:User')->findAll();
Run Code Online (Sandbox Code Playgroud)
我只想在 User 表上看到 1 个查询,并在 Site 表上进行联接,但我得到了 N+1 个查询。我还对多对一关联进行了一些测试,并得到了相同的结果。
我知道我可以使用 DQL 自己进行连接,但我想了解 fetch“EAGER” 的工作原理。
在多对多和多对一关联上获取“EAGER”的预期行为是什么?
eager关联获取的预期行为many-to-many正是您所描述的。
Post如果我们在代码中访问 3 个与发生 4 个查询many-to-many关联的对象Tags,无论我们是否使用fetch="EAGER"or fetch="LAZY":
SELECT t0.id AS id_1, t0.title AS title_2 FROM post t0
SELECT t0.id AS id_1, t0.title AS title_2 FROM tag t0 INNER JOIN post_tag ON t0.id = post_tag.tag_id WHERE post_tag.post_id = 1
SELECT t0.id AS id_1, t0.title AS title_2 FROM tag t0 INNER JOIN post_tag ON t0.id = post_tag.tag_id WHERE post_tag.post_id = 2
SELECT t0.id AS id_1, t0.title AS title_2 FROM tag t0 INNER JOIN post_tag ON t0.id = post_tag.tag_id WHERE post_tag.post_id = 3
Run Code Online (Sandbox Code Playgroud)
eager关联上的fetch 的预期行为one-to-many是不同的。通过使用fetch="EAGER"我们可以减少查询次数。
Post如果我们在代码中访问 3 个对象,这些对象one-to-many与Comments使用时发生的 1 个查询有关联fetch="EAGER":
SELECT
t0.id AS id_1,
t0.title AS title_2,
t3.id AS id_4,
t3.title AS title_5,
t3.post_id AS post_id_6
FROM post t0
LEFT JOIN comment t3 ON t3.post_id = t0.id
Run Code Online (Sandbox Code Playgroud)
但是如果我们使用 4 个查询fetch="LAZY":
SELECT t0.id AS id_1, t0.title AS title_2 FROM post t0
SELECT t0.id AS id_1, t0.title AS title_2, t0.post_id AS post_id_3 FROM comment t0 WHERE t0.post_id = 1
SELECT t0.id AS id_1, t0.title AS title_2, t0.post_id AS post_id_3 FROM comment t0 WHERE t0.post_id = 2
SELECT t0.id AS id_1, t0.title AS title_2, t0.post_id AS post_id_3 FROM comment t0 WHERE t0.post_id = 3
Run Code Online (Sandbox Code Playgroud)
切勿使用fetch="EAGER"关联many-to-many,因为它只会通过从数据库加载超出需要的数据来降低性能(但永远无法提高性能)。如果可以提高您的表现,可以选择使用fetch="EAGER"关联。one-to-many
如果我们需要减少关联查询,many-to-many我们必须编写自定义 DQL 查询。
| 归档时间: |
|
| 查看次数: |
3198 次 |
| 最近记录: |