# ANTI-PATTERN: N+1 Queries in Django ORM ## KONTEXT Django/DRF API-Entwicklung, insbesondere bei Listen-Endpoints mit Related Objects. ## WAS IST PASSIERT? ```python # SCHLECHT: N+1 Query Problem def get_matches(request): matches = Match.objects.filter(scenario_id=scenario_id) return Response([{ 'id': m.id, 'home_team': m.home_team.name, # Query für jedes Match! 'away_team': m.away_team.name, # Noch eine Query! 'venue': m.home_team.venue.name # Und noch eine! } for m in matches]) ``` Bei 100 Matches: 1 + 100 + 100 + 100 = **301 Queries** statt 1-4. ## WARUM WAR ES SCHLECHT? - **Performance:** Exponentieller Anstieg der DB-Queries mit Datenmenge - **Latenz:** Jede Query hat Overhead (Netzwerk, Parsing, Locking) - **DB-Last:** Unnötige Belastung der Datenbank - **Skalierung:** Funktioniert in Dev (10 Records), bricht in Prod (10.000 Records) ## DIE BESSERE ALTERNATIVE ```python # GUT: Optimierte Queries def get_matches(request): matches = Match.objects.filter( scenario_id=scenario_id ).select_related( 'home_team', 'away_team', 'home_team__venue', # Nested relation ) return Response([{ 'id': m.id, 'home_team': m.home_team.name, 'away_team': m.away_team.name, 'venue': m.home_team.venue.name } for m in matches]) ``` Bei 100 Matches: **1 Query** (mit JOINs). ## ERKENNUNGSREGELN - `select_related()` für ForeignKey / OneToOneField - `prefetch_related()` für ManyToMany / Reverse ForeignKey - Django Debug Toolbar zeigt Query-Anzahl - `django-query-counter` als Middleware ## CHECKLISTE - [ ] Hat jeder Listen-Endpoint `select_related`/`prefetch_related`? - [ ] Werden verschachtelte Relations berücksichtigt? - [ ] Ist die Query-Anzahl bei >100 Records akzeptabel?