首页 > 解决方案 > Doctrine 关系会影响应用程序的性能吗?

问题描述

我正在与一个新团队合作一个 Symfony 项目,由于性能问题,他们决定尽可能停止使用 Doctrine 关系。

例如,我必须存储我的“关系”的 ID,而不是使用 ManyToOne 关系。

但我想知道这是否是一个真正的问题?

问题是,它改变了检索信息等的编码方式。

标签: performancesymfonydoctrine

解决方案


性能问题很可能来自查询未优化的事实。

如果您让 Doctrine(处理查询的 Symfony 组件)自己执行查询(通过使用findBy(), findAll(),findOneBy()等),它将首先获取您所询问的内容,然后执行更多查询,因为它需要来自其他表的数据。

让我们举个最常见的例子,图书馆。

Entities

  • 作者
  • 架子

Relations

  • 一个Book有一个Author,但一个Author可以有很多Books( Book <= ManyToOne => Author)
  • 一个Book存储在一个Shelf( Book <= OneToOne => Sheilf)

现在,如果您查询 a Book,Doctrine 也将获取Shelf它,因为它是一个OneToOne关系。
但它不会 fetch Author。在您的反对中,您只能访问,book.author.id因为此信息Book本身就存在。

因此,如果在您的 Twig 视图中,您执行类似的操作{{ book.author.name }},因为在初始查询中没有获取信息,Doctrine 将添加一个额外的查询来获取有关该书作者的数据。

因此,为防止这种情况,您必须自定义查询,以便一次性获取所需的数据,如下所示:

public function getBookFullData(Book $book) {
    $qb=$this->createQueryBuilder('book');

    $qb->addSelect('shelf')
       ->addSelect('author')
       ->join('book.shelf', 'shelf')
       ->join('book.author', 'author');

    return $qb->getQuery()->getResult();
}

使用此自定义查询,您可以一次获取一本书的所有数据,因此,Doctrine 无需进行额外查询。

所以,虽然这个例子很简单,但我相信你可以理解,在大项目中,放任自流只会增加额外查询的数量。
我的一个项目,在优化之前,每页加载达到 1500 个查询......

另一方面,忽略数据库中的关系并不好。事实上,使用外键和索引的数据库比没有外键和索引的数据库要快。

如果您希望您的应用程序尽可能快,您必须使用关系来优化您的数据库查询速度,并优化 Doctrine 查询以避免过多的额外查询。

最后,我会说顺序很重要。使用ORDER BY在子节点之前获取父节点也将大大减少 Doctrine 自己可能执行的查询数量。

[边注]

您还可以更改实体注释上的 fetch 方法以“优化” Doctrine 预制查询。

  • fetch="EXTRA_LAZY
  • fetch="LAZY
  • fetch="EAGER

但它并不聪明,而且通常不能真正提供我们真正需要的东西。
因此,自定义查询是最佳选择。


推荐阅读