php - 在 getResult 上强制瀑布水化

标签 php mysql symfony caching doctrine-orm

我有一个名为“Video”的实体,附加到它的是由 ManyToOne 和 ManyToMany 关联的其他实体。

我的问题是,正在执行的查询量与常规流量不相符。例如,我在首页上执行的查询数量不定,大约有 49 个查询。

执行的绝大多数查询是因为我的视频实体的子实体在调用时没有自动初始化。当转储时,我看到私有(private)属性“is_initialized”设置为 0。当在我的模板中调用时,因为它们往往会被报告,Doctrine 然后执行查询来获取该数据。

我明白为什么 Doctrine 会这样做,如果这些数据没有被使用,为什么首先要获取它?在大多数情况下,这种行为是没有问题的。

但就我而言,我的 VideoRepository 类中有一些方法用于获取特定的视频集。所以我在这里使用 DQL。作为回应,我决定在 DQL 中将结果缓存设置为 Apc。

这是存储库中一个相对无害的示例

    /**
     * Get Videos based on recently submitted
     *
     * @param null $limit
     * @param int $page
     * @return array
     */
    public function latest($limit = null, $page = 1)
    {
        $hash = md5(sprintf("%s_%s", $limit, $page));

        $query = $this->getEntityManager()->createQueryBuilder();
        $query->select('v')->from($this->getEntityName(), 'v')
            ->where('v.published = :published')
            ->orderBy('v.datePublished', 'DESC')
            ->setParameter('published', true);

        if($limit) {
            $query->setFirstResult((int)(($page-1) * $limit));
            $query->setMaxResults($limit);
        }

        $resultQuery = $query->getQuery();
        $resultQuery->setResultCacheDriver(new ApcCache())->useResultCache(true, 300, sprintf('results_latest.%s', $hash));

        return $resultQuery->getResult();
    }

因此,在首页(正在执行 49 个查询,一旦生产数据开始命中就会执行更多查询),此方法正在请求 10 个视频。

每个视频内部都有一个关联的“产品”实体 (ManyToMany)。在每个视频的缩略图显示中,都有一个小产品图标,因此我自然需要从视频实体访问包含产品实体的 $product 属性。

此时,它正在执行 10 个以上的查询,因为 Doctrine 从来没有费心去获取每个视频的产品数据,因此它为我要求的每个图标创建一个查询,这使得我们最多 11 个(最小值,ManyToMany 意味着每个视频可以与多个产品关联)。使用 VideoRepository

中的不同方法,在此页面上针对不同的列表查询了另外 3 个视频片段

这里的问题是,虽然缓存系统会存储每个主查询的结果数据 5 分钟,但它也会存储尚未获取的产品和其他嵌入式实体。

通过简单的数学计算,这意味着使用缓存系统只为我节省了 4 个查询,使我的 Doctrine 查询计数达到 45 个。

是否有一种简单的方法可以告诉 Doctrine 在使用 getResult 时对所有子实体进行子查询和自动水合?

最佳答案

是的,更改您的查询以选择更多实体,并且学说将需要更少的延迟加载。

$query->select('v', 'sub', 'others')
        ->from($this->getEntityName(), 'v')
        ->leftJoin('v.subtitles','sub')
        ->leftJoin('v.others','others')
        ->where('v.published = :published')
        ->orderBy('v.datePublished', 'DESC')
        ->setParameter('published', true);

这将返回更多数据,并且每次您需要字幕或其他实体时,学说都不会进行连续查询。作为警告,这将返回更多数据,因此请确保此方法是可接受的。

关于php - 在 getResult 上强制瀑布水化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25314416/

相关文章:

php - 创建一个 zip 文件并下载

php - 如何检测 foreach 循环中的第一个和最后一个元素?

javascript - JS/PHP ajax 发布 Blob

java - 插入时HIbernate语法sql错误

symfony - 逻辑异常 : Container extension "jms_serializer" is not registered

dependency-injection - 通过 services.yml 将自定义实体存储库类传递给服务

php - 更改 Faker 在 Lumen 中的本地化

php - 使用php在数据库的单列中插入多个值

php - 将数据插入两个数据库,其中一个是第三方数据库

date - Symfony -> 如何使用 Doctrine 使创建和修改的字段动态化?