我遇到了使用Doctrine的可怕N +1问题,特别是在获取具有双向一对一关系的表时。我现在明白了在Doctrine中应该避免双向的一对一关系,但是我正在使用一个旧的代码库,我想尽可能少地改变,因为我不知道是否会有副作用。
Context
我有一个Intervention
表,与User
表有多对一关系。User
表与UserIdentity
表具有一对一关系。关系由User
Map,由UserIdentity
反演
问题
我在查询Intervention
表并加入User
关系时遇到了N +1问题。对于每个唯一的User
,进行查询以获取对应的UserIdentity
。这导致大约1K个唯一查询。
我以前也遇到过类似的问题,通过将一对一关系的反面添加到SELECT调用中,然后左加入它来解决这个问题。然而,在这种情况下,它似乎不起作用。我怀疑这是因为UserIdentity
不是Intervention
的直接关联,而是User
的直接关联。
我所尝试的
以下是我的代码到目前为止的样子。我把所有与问题无关的东西都剪掉了。
$alias = "intervention";
$qb = $this->manager
->createQueryBuilder()
->select("partial $alias .{id, uuid, purpose, type, creation, detectorUuid}, intervention_user, trackdechetsIdentity, fibsd")
->from(Intervention::class, $alias)
;
$qb = $qb
->leftJoin("$alias.user", 'intervention_user')
->leftJoin("intervention_user.trackdechetsIdentity", "trackdechetsIdentity") // This is the UserIdentity entity
->leftJoin("$alias.fibsd", "fibsd") // Solving another N+1 problem, this time it's a direct one-to-one relation
->orderBy("$alias.id", 'DESC')
;
return $qb->getQuery()->getResult();
这会生成与我的数据库中用户数量一样多的查询。有人知道怎么解决这个问题吗?
1条答案
按热度按时间rqmkfv5c1#
我会回答我自己的问题
我还是不知道为什么我不能用直接的一对一的关系来解决这个问题。然而,使用this answer的解决方案做得很好。
通过将关系从一对一更改为多对一/一对多允许延迟加载并摆脱N+1问题。请参阅链接的答案以获得更多解释