mariadb 具有嵌套一对一关系的原则N + 1问题

t1rydlwq  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(110)

我遇到了使用Doctrine的可怕N +1问题,特别是在获取具有双向一对一关系的表时。我现在明白了在Doctrine中应该避免双向的一对一关系,但是我正在使用一个旧的代码库,我想尽可能少地改变,因为我不知道是否会有副作用。

Context

我有一个Intervention表,与User表有多对一关系。User表与UserIdentity表具有一对一关系。关系由UserMap,由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();

这会生成与我的数据库中用户数量一样多的查询。有人知道怎么解决这个问题吗?

rqmkfv5c

rqmkfv5c1#

我会回答我自己的问题
我还是不知道为什么我不能用直接的一对一的关系来解决这个问题。然而,使用this answer的解决方案做得很好。
通过将关系从一对一更改为多对一/一对多允许延迟加载并摆脱N+1问题。请参阅链接的答案以获得更多解释

相关问题