Perf: customer press-releases-Liste ueber UNION statt OR-Paginate

Die Uebersicht /admin/me/press-releases war auch fuer leere Konten ~2s: der OR-Filter in scopeAccessibleBy zwang die Paginator-count(*) zum Full-Scan (EXPLAIN type=ALL, ~174k Zeilen) und den Zeilen-Fetch bei 0 Treffern zum vollen created_at-Index-Scan (~1s). Neue PressRelease::accessiblePageFor() nutzt dieselbe index-freundliche UNION wie accessibleStatusCountsFor(): schmale UNION liefert die Seiten-IDs ueber user_id-/company_id-Index, danach nur 25 Modelle hydratisiert; Total via schnellem UNION-count. Messung: leer ~2000ms -> 167ms, groesstes Konto (20.830 PMs) ~740ms -> 468ms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-02 10:55:45 +00:00
parent 90f3245e41
commit db7c1dfbf1
3 changed files with 164 additions and 11 deletions

View file

@ -135,17 +135,16 @@ new #[Layout('components.layouts.app'), Title('Meine Pressemitteilungen')] class
PressReleaseStatus::Archived->value => $statusCountsRaw[PressReleaseStatus::Archived->value] ?? 0,
];
$prs = PressRelease::accessibleBy($user)
->tap($applyCompanyFilter)
->with('company:id,name')
->when(filled($this->search), function ($q): void {
$term = $this->search;
$q->where('title', 'like', '%' . $term . '%');
})
->when($this->statusFilter !== 'all', fn($q) => $q->where('status', $this->statusFilter))
->when($this->portalFilter !== 'all', fn($q) => $q->where('portal', $this->portalFilter))
->orderBy(in_array($this->sortBy, ['title', 'status', 'created_at']) ? $this->sortBy : 'created_at', $this->sortDir)
->paginate(25);
// Der Firmen-Scope plus die Suchleiste/Status-/Portal-Filter werden in
// beide UNION-Zweige gezogen (siehe PressRelease::accessiblePageFor()).
$applyListFilters = function ($query) use ($applyCompanyFilter): void {
$applyCompanyFilter($query);
$query->when(filled($this->search), fn ($q) => $q->where('title', 'like', '%'.$this->search.'%'))
->when($this->statusFilter !== 'all', fn ($q) => $q->where('status', $this->statusFilter))
->when($this->portalFilter !== 'all', fn ($q) => $q->where('portal', $this->portalFilter));
};
$prs = PressRelease::accessiblePageFor($user, $applyListFilters, $this->sortBy, $this->sortDir);
return [
'pressReleases' => $prs,