操作
サポート #2207
未完了
アデ
廣僚
在庫管理の年度別集計をリファクタリング
サポート #2207:
在庫管理の年度別集計をリファクタリング
開始日:
2026/01/13
期日:
進捗率:
50%
予定工数:
対象ページURL:
起票元ID:
自動起票の種別:
却下理由:
説明
指示内容¶
問題¶
- 管理画面アクセス
- Livewire が state を評価
- Filament が summarizer を呼ぶ
- sum() が 重い SQL を発行
- DB が計算
- PHP が待つ
- Nginx が待つ
- fastcgi_read_timeout 超過
- upstream timed out
やるべき修正(優先度順)¶
1. sum() を view 描画から外せ¶
Blade / Livewire / Summarizer 内で集計 ❌
Controller / Page クラスの mount() で 1回だけ 実行
public int $totalSales;
public function mount()
{
$this->totalSales = Order::where(...)->sum('amount');
}
2. キャッシュしろ(必須)¶
$this->totalSales = Cache::remember(
"sales_sum_fy_{$year}",
3600,
fn () => Order::where(...)->sum('amount')
);
3. 年度別集計テーブルを作れ¶
daily / monthly / yearly summary
cron or queue で更新
在庫・売上系は必ず事前集計。
レベル1:インクリメンタル集計(最優先)
考え方
データが「増減した瞬間」にだけ計算する
「見るとき」は読むだけ
具体例(売上合計)
❌ 毎回
SELECT SUM(amount) FROM orders WHERE ...
✅ 書き込み時
DB::table('sales_summary')
->where('year', $year)
->increment('total_amount', $amount);
ファイル
アデ アルドリノ デフリン さんが9日前に更新
- ステータス を 新規 から 進行中 に変更
- 進捗率 を 0 から 30 に変更
アデ アルドリノ デフリン さんが9日前に更新
- ステータス を 進行中 から フィードバック に変更
- 担当者 を アルドリノ デフリン から 廣瀬 僚一 に変更
- 進捗率 を 30 から 50 に変更
対応内容¶
| # | 内容 | 対象 |
|---|---|---|
| 1 | インデックスを 3 つ追加 |
sales_slips.date、sales_slip_items.product_id、purchases (product_id, date)
|
| 2 | 在庫数を全商品分まとめて集計 | 在庫確認画面、在庫確認エクスポート |
| 3 | 月別売上の条件を日付範囲に変更 | ダッシュボード(今月の売上・月別グラフ) |
-
1. インデックス: 計測した結果、売上集計の結合列(
client_id・sales_rep_id・area_idなど)へのインデックスは、MySQL が遅い結合方法を選ぶことで一部の集計画面が 10〜25ms 遅くなったため、追加していません。効果のあった 3 つに限定しています。 -
2. 在庫数の一括集計:
Product::withStockFigures()を追加し、全商品分の 4 項目を 2 つの集計サブクエリでまとめて取得するように変更しました。表示・出力される値は従来と同じです。 -
3. ダッシュボード:
whereYear()・whereMonth()ではインデックスが使われないため、whereBetween()(月初〜月末)に変更しました。
計測結果(ローカル環境)¶
| 対象 | 変更前 | 変更後 |
|---|---|---|
| 在庫確認エクスポート(全 170 商品) | 1,388ms・1,193 クエリ | 15ms・3 クエリ |
| 在庫確認エクスポート(商品区分で絞り込み) | 739ms・731 クエリ | 8ms・3 クエリ |
| 在庫確認画面(10 件表示) | 324ms・228 クエリ | 約 110ms・14 クエリ |
| 在庫確認(100 件分) | 約 730ms・約 700 クエリ | 25ms・1 クエリ |
| 年度別売上集計(SQL 時間) | 81ms | 38ms |
| ダッシュボードのウィジェット | 9〜24ms | 3〜8ms |
| その他の売上集計 7 画面 | 35〜125ms | 変化なし(±5ms) |
値の確認:
- 全 175 商品 × 4 項目で、新しい集計と従来の計算結果が完全に一致
- 在庫確認エクスポート・ダッシュボードの値が変更前と一致(エクスポートで文字列だった数値 3 セルが、数値として出力されるようになった点のみ変化)
- 管理画面の全 35 ページの表示と、自動テストが成功
指示内容への対応状況¶
| 指示 | 対応 | 理由 |
|---|---|---|
| 1. sum() を view 描画から外し、mount() で 1 回だけ実行 | 一部対応 | 実際に描画中に大量の sum() を実行していたのは在庫確認画面だったため、そこを一括集計に変更。売上集計画面の Summarizer は高速で、mount() に移すとフィルタと合計が連動しなくなるため変更せず |
| 2. キャッシュ | 対応なし | 集計は十分に高速になり、キャッシュすると伝票保存直後に古い合計が表示されるおそれがあるため |
| 3. 年度別集計テーブル/インクリメンタル集計 | 対応なし | 現在のデータ量(明細約 6,700 件)では不要で、集計値のずれのリスクが大きいため。なお現在庫数(products.stock)は、すでに仕入・売上の保存時に増減する方式になっている |
データ量が大きく増えた場合(目安として現在の 10 倍以上)は、2・3 を再検討します。
操作