为了账号安全,请及时绑定邮箱和手机立即绑定

Doctrine 在水合作用过程中增加了额外的查询,导致 n+1 问题与“正常”的一对一和自引用关系

Doctrine 在水合作用过程中增加了额外的查询,导致 n+1 问题与“正常”的一对一和自引用关系

PHP
繁花不似锦 2023-03-04 10:51:37
News使用一对多的自引用方法相互关联(一个消息是父消息,可以有多个子消息)。更重要的是 each与和News具有正常的(非自引用的)一对一关系。当我运行简单的 DQL 时:EventGallerySELECT n FROM App\Entity\News n WHERE n.parent = :id然后通过设置getResults默认值的方法对结果进行水合HYDRATION_OBJECT,在方法内部的某处进行额外的查询getResults。SELECT t0.* FROM event t0 WHERE t0.news_id = 2 AND ((t0.deleted_at IS NULL));SELECT t0.* FROM gallery t0 WHERE t0.news_id = 2 AND ((t0.deleted_at IS NULL));SELECT t0.* FROM event t0 WHERE t0.news_id = 1 AND ((t0.deleted_at IS NULL));SELECT t0.* FROM gallery t0 WHERE t0.news_id = 1 AND ((t0.deleted_at IS NULL));第一次查询选择的新闻的孩子在哪里和在哪里news_id = 1。news_id = 2News也没有自引用的一对多关系(我在这里忽略了它们),但是 hydration 没有对它们进行额外的查询。parent仅当语句中涉及关系时才会出现此问题where。如何重现// news Entity/** * @ORM\Entity(repositoryClass="App\Repository\NewsRepository") * @ORM\Table(uniqueConstraints={@UniqueConstraint(name="news_slug_deleted", columns={"slug","deleted_at"})}) *class News {    use SoftDeleteableEntity;    /**     * @ORM\Id()     * @ORM\GeneratedValue()     * @ORM\Column(type="integer")     */    private $id;    /**     * @ORM\Column(type="string", length=255)     */    private $title;    /**     * @Gedmo\Slug(fields={"title"})     * @ORM\Column(length=128)     */    private $slug;/**     * @ORM\OneToOne(targetEntity="App\Entity\Gallery", mappedBy="news", cascade={"persist", "remove"}, orphanRemoval=true)     *     * @var Gallery     */    private $gallery;    /**     * @ORM\OneToOne(targetEntity="App\Entity\Event", mappedBy="news", cascade={"persist", "remove"}, orphanRemoval=true)     *     * @var Event     */    private $event;    /**     * One News has Many News.     * @ORM\OneToMany(targetEntity="News", mappedBy="parent")     */    private $children;    /**     * Many News have One News.     * @ORM\ManyToOne(targetEntity="News", inversedBy="children")     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)     */    private $parent;}
查看完整描述

1 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

您在该实体中有几个反向 OneToOne 关系。


反向 OneToOne 关系不能被 Doctrine 延迟加载,并且很容易成为性能问题。


如果您真的需要将这些关系映射到反面(而不仅仅是在拥有方),请确保明确地进行适当的连接,或者将这些关联标记为以便FETCH=EAGERDoctrine 为您进行连接。


例如,避免可怕的“n+1”问题的查询是:


SELECT n, g, e

    FROM App\Entity\News n

    LEFT JOIN n.gallery g

    LEFT JOIN n.event e

WHERE n.parent = :id



查看完整回答
反对 回复 2023-03-04
  • 1 回答
  • 0 关注
  • 112 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号