Skip to content

Conversation

@nobuhiko
Copy link
Contributor

概要

商品詳細ページで発生していたN+1クエリ問題を解決しました。

問題

  • findWithSortedClassCategories()がProductStockとTaxRuleをEager Loadingしていなかった
  • Product::_calc()が各ProductClassに対してlazy loadをトリガーし、N+1クエリが発生
  • 352個のProductClassを持つ商品で987クエリ(2300ms)を記録

解決策

  • ProductStockとTaxRuleのleftJoinによるEager Loadingを追加
  • eccube_result_cache_lifetime_shortによる結果キャッシュを有効化
  • 商品一覧ページで既に使用されている最適化パターンを適用

期待される効果

  • クエリ削減: 987クエリ → 3クエリ (99.7%削減)
  • 初回表示: 約60-70%改善
  • 2回目以降: キャッシュヒットでさらに高速化

変更内容

1. ProductRepository::findWithSortedClassCategories()

  • ProductStockとTaxRuleをEager Loadingに追加
  • 結果キャッシュの設定を追加

2. ProductRepositoryTest::testFindWithSortedClassCategoriesWithManyProductClasses()

  • 100個のProductClassを持つ商品でN+1問題が解決されているかを検証
  • Doctrineクエリロガーで_calc()実行前後のクエリ数をカウント
  • 追加クエリが実行されないことをアサート

セキュリティレビュー結果

セキュリティチェック: 合格

  • SQLインジェクション: 問題なし(パラメータバインディング使用)
  • XSS: 問題なし(データ取得のみ)
  • 認証・認可: 問題なし(既存の仕組みを維持)
  • 情報漏洩: 問題なし(公開情報のみ)
  • キャッシュセキュリティ: 問題なし(10秒短期キャッシュ)
  • DoS対策: 改善(リソース消費削減)

詳細なセキュリティレポートはコメントを参照してください。

テスト

bin/phpunit tests/Eccube/Tests/Repository/ProductRepositoryTest.php::testFindWithSortedClassCategoriesWithManyProductClasses

参考

EC-CUBE 4.3既存実装(findProductsWithSortedClassCategories)のパターンを商品詳細にも適用


🤖 Generated with Claude Code

## Problem
- findWithSortedClassCategories() for product detail page was not eagerly loading ProductStock and TaxRule
- Product::_calc() triggered lazy loading for each ProductClass, causing N+1 queries
- For products with 352 ProductClasses, this resulted in 987 queries (2300ms)

## Solution
- Added eager loading of ProductStock and TaxRule via leftJoin
- Enabled query result cache with eccube_result_cache_lifetime_short
- Applied the same optimization pattern already used in findProductsWithSortedClassCategories() for product list page

## Expected Impact (based on helmet.jp optimization memo)
- Query reduction: 987 queries → 3 queries (99.7% reduction)
- Initial page load: ~60-70% improvement
- Second access: Further improvement with cache hit

## Changes
1. ProductRepository::findWithSortedClassCategories()
   - Added ProductStock and TaxRule to eager loading
   - Added result cache configuration

2. ProductRepositoryTest::testFindWithSortedClassCategoriesWithManyProductClasses()
   - Added test with 100 ProductClasses to verify N+1 problem is solved
   - Uses Doctrine query logger to count queries before/after _calc()
   - Asserts no additional queries are executed (N+1 solved)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant