390 lines
9.3 KiB
Markdown
390 lines
9.3 KiB
Markdown
# 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.
|