# 11 – Noch zu tun: Optimierungen **Stand:** 2026-04-29 **Kontext:** Admin-Performance, Livewire/Volt-Aufteilung, Slow-Request-Auswertung Dieses Dokument fasst die noch offenen Optimierungspunkte nach der bisherigen Admin-Performance-Runde zusammen. Bereits umgesetzt sind u. a. aggregierte Dashboard-Queries, Admin-Statistik-Caches, Fulltext-Suche mit Fallback, kleinere Pagination, optimierte `withCount()`-Nutzung, Slow-Admin-Request-Logging, eigener `admin_slow`-Log-Kanal, Artisan-Report und eine Admin-Report-Seite. --- ## 1. Slow-Admin-Reports mit echten Daten auswerten **Priorität:** hoch **Ziel:** Nicht weiter auf Verdacht optimieren, sondern anhand echter Slow-Requests. ### Aktueller Stand Slow Admin Requests werden in den eigenen Daily-Log-Kanal geschrieben: ```bash storage/logs/admin-slow-*.log ``` Die Auswertung ist verfügbar über: ```bash php artisan admin:slow-requests ``` und im Admin unter: ```text Reports > Performance ``` ### Noch zu tun 1. Admin mit realistischem Datenbestand bedienen. 2. Typische langsame Seiten gezielt öffnen: - Dashboard - Benutzerliste - Benutzer bearbeiten - Firmenliste - Firma anzeigen - Kontakte - Pressemitteilungen - Reports > Performance 3. Danach den Report auswerten: ```bash php artisan admin:slow-requests --top=20 --limit=50 ``` 4. Auffällige Routen priorisieren: - höchste `duration_ms` - höchste `database_time_ms` - höchste `query_count` - wiederkehrende Slow Queries ### Ergebnis Die nächsten Optimierungen sollten aus dem Report abgeleitet und nicht pauschal durchgeführt werden. --- ## 2. EXPLAIN für Top-Slow-Queries prüfen **Priorität:** hoch **Ziel:** Sicherstellen, dass neue Indexe und Fulltext-Indexe von MySQL/PostgreSQL tatsächlich genutzt werden. ### Aktueller Stand Der Slow-Request-Reporter versucht für SELECT/CTE-Slow-Queries automatisch ein `EXPLAIN` bzw. bei SQLite `EXPLAIN QUERY PLAN`. ### Noch zu prüfen Besonders relevant sind Queries auf: - `press_releases` - `companies` - `contacts` - `users` - `categories` - `category_translations` ### Prüffragen - Wird bei Suchabfragen der Fulltext-Index genutzt? - Wird bei Listen `ORDER BY created_at` / `ORDER BY id` ein passender Index genutzt? - Sind Sortierung und Filter in derselben Index-Reihenfolge abgedeckt? - Gibt es noch `SCAN TABLE` / Full Table Scans auf großen Tabellen? - Gibt es `whereHas()`/`has()`-Queries, die durch `distinct()`/Aggregationen ersetzt werden sollten? ### Mögliche Folgearbeiten - Zusätzliche zusammengesetzte Indexe ergänzen. - Sortier-/Filterkombinationen in Listen begrenzen. - Query-Formulierungen vereinfachen, wenn der Planner Indexe nicht nutzt. --- ## 3. Livewire-Komponenten gezielt aufteilen **Priorität:** hoch bis mittel **Ziel:** Große Admin-Komponenten wartbarer machen und teure Teilbereiche als Livewire-Inseln isolieren. Livewire-Aufteilung ist nicht pauschal ein Performance-Gewinn. Sie lohnt sich vor allem, wenn ein Teilbereich eigene Daten lädt, eigene Live-Suche hat oder unabhängig rerendern kann. ### 3.1 `admin.users.edit` aufteilen **Priorität:** hoch **Datei:** `resources/views/livewire/admin/users/edit.blade.php` Diese Komponente ist der größte Refactoring-Kandidat. Sie bündelt derzeit: - User-Basisdaten - Profil - Rollen - Firmenzuordnung - Kontaktzuordnung - Kontaktbearbeitung - Rechnungsadresse - Live-Suchen - direkte Persistierung bei Link/Unlink-Aktionen ### Empfohlenes Zielbild `admin.users.edit` bleibt Page-Wrapper für: - User-ID - Basisdaten - Save-Flow - grobe Navigation / Layout Auslagern: 1. `admin.users.partials.profile-form` - zunächst Blade-Partial ohne eigenes Livewire - geringes Risiko 2. `admin.users.partials.billing-address-form` - zunächst Blade-Partial ohne eigenes Livewire - geringes Risiko 3. `admin.users.company-links` - eigene Volt-Komponente - verwaltet Firmen-Live-Suche, Rollen pro Firma, Link/Unlink - reduziert Rerenders im Hauptformular 4. `admin.users.contact-links` - eigene Volt-Komponente - verwaltet Kontakt-Live-Suche und Kontakt-Zuordnung - sollte nach `company-links` umgesetzt werden ### Empfohlene Reihenfolge 1. Nur Blade-Partials extrahieren, keine Logik ändern. 2. Tests unverändert laufen lassen. 3. Firmenzuordnung in eigene Komponente ziehen. 4. Kontaktzuordnung in eigene Komponente ziehen. 5. Danach Slow-Reports vergleichen. ### Risiken - Aktuell persistieren Link/Unlink-Aktionen direkt. - Firmen- und Kontaktzuordnung hängen fachlich zusammen. - Zu starke Trennung kann Events/State-Synchronisierung unnötig komplex machen. Deshalb nur schrittweise aufteilen. --- ## 4. `companies.show` Kontakte-Tab isolieren **Priorität:** mittel **Datei:** `resources/views/livewire/admin/companies/show.blade.php` ### Aktueller Stand Die Komponente lädt Übersichtsdaten, Pressemitteilungen, User, Counts und bei aktivem Kontakte-Tab zusätzlich Kontakte und Kontakt-Lookup. ### Zielbild `admin.companies.show` bleibt für: - Firmenkopf - Übersicht - Pressemitteilungen - User-Zuordnungen Neue Komponente: ```text admin.companies.contacts-tab ``` Aufgaben: - Kontaktliste laden - Kontakt-Suche - vorhandene Kontakte zuordnen - Limit-/Hinweislogik für große Kontaktmengen ### Nutzen - Kontakte-Tab lädt unabhängig. - Suchen im Kontakte-Tab rerendern nicht die komplette Firmen-Detailseite. - Klarere Verantwortlichkeit. --- ## 5. Listen erst nach Messwerten weiter aufteilen **Priorität:** mittel bis niedrig Diese Komponenten sind bereits deutlich optimiert und sollten nicht ohne Slow-Report-Befund refactored werden: - `admin.users` - `admin.contacts.index` - `admin.companies.index` - `admin.press-releases.index` - `admin.categories.index` ### Bereits umgesetzt - `simplePaginate(50)` - aggregierte Stats - zentrale Cache-Invalidierung - Fulltext-Suche mit Fallback - limitierte Combobox-/Lookup-Ergebnisse - `withCount()` nur gezielt oder nachträglich für sichtbare Datensätze ### Noch möglich Nur bei messbarer Langsamkeit: - weitere Sortieroptionen begrenzen - zusätzliche zusammengesetzte Indexe - einzelne Filter als eigene Komponenten - Export-/Bulk-Actions asynchronisieren --- ## 6. Billing-Bereiche finalisieren **Priorität:** mittel **Dateien:** - `resources/views/livewire/admin/invoices/index.blade.php` - `resources/views/livewire/admin/payments/index.blade.php` - `resources/views/livewire/admin/coupons/index.blade.php` ### Aktueller Stand Diese Bereiche enthalten noch Dummy-/Platzhalterdaten. ### Noch zu tun bei echter Implementierung - echte Models anbinden - `simplePaginate()` statt Vollmengen - aggregierte Stats statt Einzelcounts - Indexe für Filter/Sortierung - Suchfilter mit passenden Datenbankindizes - Tests für Filter, Pagination und Berechtigungen --- ## 7. Rollen-Index nur bei Bedarf optimieren **Priorität:** niedrig **Datei:** `resources/views/livewire/admin/roles/index.blade.php` ### Aktueller Stand Die Rollenübersicht lädt alle Rollen mit: ```php withCount(['users', 'permissions']) ``` Das ist bei wenigen Systemrollen unproblematisch. ### Optimieren, falls: - viele Custom-Rollen entstehen - der Slow-Report `admin.roles.index` auffällig zeigt ### Mögliche Maßnahmen - Pagination - Cache für Rollenübersicht - Counts nur bei Bedarf anzeigen --- ## 8. Optional: Slow-Requests zusätzlich in Datenbank persistieren **Priorität:** optional **Ziel:** Langfristige Trends statt reiner Log-Auswertung. ### Aktueller Stand Logs sind bewusst schlank und reichen für Debugging. ### Datenbank wäre sinnvoll, wenn: - historische Trends benötigt werden - Performance-Regressionen über Releases verglichen werden sollen - Reports filterbar über längere Zeiträume bleiben müssen - Log-Rotation Daten zu früh entfernt ### Mögliche Tabelle ```text admin_slow_requests ``` Felder: - `route_name` - `path` - `method` - `status_code` - `user_id` - `duration_ms` - `database_time_ms` - `query_count` - `slow_queries` JSON - `requested_at` Vorerst nicht zwingend notwendig. --- ## 9. Optional: Report-UI erweitern **Priorität:** niedrig bis mittel Die neue Seite `Reports > Performance` kann später erweitert werden um: - CSV-Export - Zeitraum-Schnellfilter: heute, 7 Tage, 30 Tage - Gruppierung nach Tag/Stunde - direkte Links zu Admin-Routen, sofern Parameter rekonstruierbar sind - Badges für Schwellenwerte - Vergleich vor/nach Optimierung --- ## 10. Empfohlene nächste Umsetzung Wenn keine neuen Slow-Report-Befunde vorliegen: 1. `users.edit` in Blade-Partials für Profil und Rechnungsadresse aufteilen. 2. Tests unverändert laufen lassen. 3. Firmenzuordnung als eigene Volt-Komponente extrahieren. 4. Kontaktzuordnung als eigene Volt-Komponente extrahieren. 5. Danach Slow-Report erneut vergleichen. Wenn Slow-Report-Befunde vorliegen: 1. langsamste Route identifizieren. 2. Top-Slow-Queries mit EXPLAIN prüfen. 3. nur diese Route/Query optimieren. 4. Test ergänzen. 5. erneute Messung. --- ## 11. Aktuelle Empfehlung Der nächste konkrete Code-Schritt sollte sein: ```text admin.users.edit refactor phase 1 ``` Umfang: - Profil-Formular in Partial auslagern - Rechnungsadresse in Partial auslagern - keine Logikänderung - bestehende `UserManagementTest`-Tests weiterverwenden Danach: ```text admin.users.company-links als eigene Volt-Komponente ``` Das bringt den besten Mix aus Wartbarkeit, geringerem Rerender-Risiko und überschaubarem Refactoring-Risiko.