1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【EC-CUBE 4】重い集計クエリをSymfony Cacheで高速化する方法

1
Posted at

【EC-CUBE 4】重い集計クエリをSymfony Cacheで高速化する方法

EC-CUBE 4の案件で、商品数を表示している箇所があり商品数が多くパフォーマンスが悪い問題がありました。
Symfony Cache を使ってある程度解決することができたので備忘録として記事にしました。
あくまで例として簡単に作ったものなので、ご自身の環境に合わせて適宜読み替えてください。

課題

  • 集計クエリが毎リクエスト実行される
  • 頻繁に更新されないデータなのに、毎回DBにアクセスしている

解決策

Symfony Cacheを使い、集計結果を**300秒(5分)**キャッシュする。

実装

1. カスタムRepositoryを作成

<?php

namespace Customize\Repository;

use Doctrine\Persistence\ManagerRegistry;
use Eccube\Common\EccubeConfig;
use Eccube\Repository\ProductRepository;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;

class CachedProductRepository extends ProductRepository
{
    private CacheInterface $cache;
    private const CACHE_LIFETIME = 300;

    public function __construct(
        ManagerRegistry $registry,
        EccubeConfig $eccubeConfig,
        CacheInterface $cache
    ) {
        parent::__construct($registry, $eccubeConfig);
        $this->cache = $cache;
    }

    /**
     * カテゴリ別商品数を取得(キャッシュ付き)
     */
    public function getProductCountByCategory(): array
    {
        return $this->cache->get('product_count_by_category', function (ItemInterface $item) {
            $item->expiresAfter(self::CACHE_LIFETIME);

            return $this->createQueryBuilder('p')
                ->select('c.id, c.name, COUNT(p.id) as product_count')
                ->innerJoin('p.ProductCategories', 'pc')
                ->innerJoin('pc.Category', 'c')
                ->where('p.Status = :status')
                ->setParameter('status', 1)
                ->groupBy('c.id')
                ->getQuery()
                ->getArrayResult();
        });
    }
}

2. services.yaml

services:
    Customize\Repository\CachedProductRepository:
        autowire: true
        arguments:
            $cache: '@cache.app' # 書かなくてもいいと思うが明示してくと安心

cache->get() の動作

  1. キャッシュあり → 即座に返却(DBアクセスなし)
  2. キャッシュなし → クエリ実行 → キャッシュ保存 → 返却

効果

指標 Before After
キャッシュ有効期間 なし 300秒
5分間のDBクエリ 最大300回 1回

補足

  • cache.appはファイルベースのキャッシュ(デフォルト)
  • キャッシュキーは一意になるよう命名すること
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?