Skip to content

Improve dashboard performance with database-level aggregation#6570

Open
nobuhiko wants to merge 2 commits intoEC-CUBE:4.3from
nobuhiko:feature/dashboard-performance-improvement
Open

Improve dashboard performance with database-level aggregation#6570
nobuhiko wants to merge 2 commits intoEC-CUBE:4.3from
nobuhiko:feature/dashboard-performance-improvement

Conversation

@nobuhiko
Copy link
Contributor

@nobuhiko nobuhiko commented Jan 15, 2026

概要

管理画面ホームの売上データ表示において、大量の注文データがある場合にパフォーマンスが低下する問題を解決しました。Issue #6558 で報告された通り、従来はPHP側で全注文データを読み込んで集計していましたが、データベース側で集計することで大幅なパフォーマンス改善を実現しました。

問題

従来の実装では、売上データを表示する際に以下の処理を行っていました:

  1. Orderエンティティ全件をPHPメモリに読み込み
  2. PHP側でループ処理して集計

この方式では、注文数が増えるほど以下の問題が発生:

  • メモリ使用量の増加
  • 処理時間の増加(O(n)の計算量)
  • データベースからの大量データ転送

解決策

データベース側で集計を行うように変更:

  • GROUP BYSUM()COUNT()を使用したデータベースレベルの集計
  • 必要最小限のデータのみをPHPに返却
  • 処理時間がデータ量にほぼ依存しない(O(1)に近い)

変更内容

1. DateFormat DQL関数の実装 (src/Eccube/Doctrine/ORM/Query/DateFormat.php)

クロスデータベース対応の日付フォーマット関数を追加:

  • MySQL: DATE_FORMAT()
  • PostgreSQL: TO_CHAR()
  • SQLite: STRFTIME()

2. OrderRepository の拡張 (src/Eccube/Repository/OrderRepository.php)

public function getSalesDataGroupedByDate($fromDate, $toDate, array $excludeStatuses, $format = 'Y/m/d')

データベース側で日付ごとに売上を集計する新メソッドを追加。

3. AdminController の最適化 (src/Eccube/Controller/Admin/AdminController.php)

  • getData() メソッドを修正し、新しいリポジトリメソッドを使用
  • パラメータバインディングの修正(:excludesexcludes
  • 日付境界条件の修正(<=<

4. パフォーマンステストの追加 (tests/Eccube/Tests/Web/Admin/IndexControllerTest.php)

  • 100件の注文データでのロード時間テスト(2秒未満)
  • メモリ使用量テスト(15MB未満、実測値: 11.7MB)
  • N+1問題の検証テスト

パフォーマンス検証結果

テスト環境

  • 注文データ: 34,807件
  • データベース: MySQL 8.4

結果

  • ✅ ページ読み込み時間: 2秒未満
  • ✅ メモリ使用量: 大幅削減
  • ✅ データ量に依存しない安定したパフォーマンス

技術的考慮事項

セキュリティ

  • ✅ SQLインジェクション対策: 全パラメータを適切にバインディング
  • ✅ フォーマット文字列: ハードコード値のみ使用
  • ✅ デバッグコード: 全て削除済み

後方互換性

  • ✅ 既存のイベントシステムを維持
  • ✅ 表示内容は変更なし
  • ✅ APIインターフェースは変更なし

データベース互換性

  • ✅ MySQL
  • ✅ PostgreSQL
  • ✅ SQLite

スクリーンショット

管理画面ホーム(34,807件の注文データで高速表示)

管理画面ホーム

テスト

実行したテスト

# 全IndexControllerテスト(8テスト)
vendor/bin/phpunit tests/Eccube/Tests/Web/Admin/IndexControllerTest.php

# パフォーマンステスト(2テスト)
vendor/bin/phpunit tests/Eccube/Tests/Web/Admin/IndexControllerTest.php --group performance

テスト結果

  • ✅ 全8テストが成功
  • ✅ 既存の売上データ表示テストが正常動作
  • ✅ パフォーマンステストが基準内で合格

関連Issue

Fixes #6558

チェックリスト

  • コードがPSR-12に準拠
  • テストケースを追加(パフォーマンステスト2件)
  • 既存のテストが通過(全8テスト)
  • 後方互換性を維持
  • セキュリティ考慮事項を確認(SQLインジェクション対策済み)
  • クロスデータベース対応(MySQL/PostgreSQL/SQLite)
  • パフォーマンス検証実施(34,807件のデータで確認)

🤖 Generated with Claude Code

@nobuhiko nobuhiko force-pushed the feature/dashboard-performance-improvement branch 2 times, most recently from 0a62f8c to 59ad6e7 Compare January 15, 2026 03:08
This commit addresses Issue EC-CUBE#6558 by optimizing the sales data
calculation on the admin dashboard. Previously, the system loaded
all Order entities into memory and performed calculations in PHP,
which caused performance issues with large datasets.

Changes:
- Added DateFormat DQL function for cross-database date formatting
- Implemented getSalesDataGroupedByDate() in OrderRepository for
  database-level aggregation using GROUP BY, SUM, and COUNT
- Updated AdminController to use the new repository method
- Fixed parameter binding issues (removed colons from parameter names)
- Fixed date boundary conditions in getSalesByDay() and getSalesByMonth()
- Added performance tests to verify efficiency with large datasets
- Added dashboard screenshot

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@nobuhiko nobuhiko force-pushed the feature/dashboard-performance-improvement branch from 59ad6e7 to f9fd37b Compare January 15, 2026 03:20
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