Bestätige es zuerst, indem du Queries zählst, lokal mit der Django Debug Toolbar oder mit assertNumQueries in einem Test. Das Muster ist eine Schleife, die ein verknüpftes Objekt anfasst, was pro Zeile eine Query auslöst, weil Querysets lazy sind. Vorwärtsbeziehungen behebst du mit select_related, das einen Join macht, umgekehrte oder Many-to-Many-Beziehungen mit prefetch_related, das eine zusätzliche Query fährt.
Warum Interviewer das fragen
Das ist der mit Abstand häufigste Performance-Bug in ORM-gestützten Anwendungen, also grenzt es an eine Jobanforderung. Interviewer wollen sehen, dass du misst, bevor du optimierst, dass du Queryset-Laziness als die zugrunde liegende Ursache verstehst und dass du weißt, dass select_related und prefetch_related unterschiedliche Beziehungsformen lösen. Einen Regressionstest zu schreiben statt nur zu patchen ist das Senior-Signal.
So baust du deine Antwort auf
- Sag, dass du zuerst die Query-Anzahl misst.
- Erklär Laziness als Grundursache.
- Ordne select_related und prefetch_related den Beziehungstypen zu.
- Sichere die Lösung mit einem Query-Count-Test ab.
Beispielantwort
Messen kommt zuerst, denn ORM-Performance zu raten ist ein verschwendeter Nachmittag. Lokal schalte ich die Debug Toolbar ein oder logge Queries auf Debug-Level, und wenn es schon in Produktion ist, schaue ich in den Trace, wo ein Endpunkt, der vierhundert fast identische Selects abfeuert, unverkennbar ist. Die Ursache ist, dass ein Queryset die Datenbank erst anfasst, wenn du darüber iterierst, und der Zugriff auf einen Foreign Key pro Zeile diese Beziehung lazy nachlädt. Für einen Vorwärts-Foreign-Key ergänze ich select_related, was daraus einen Join und eine Query macht. Für umgekehrte oder Many-to-Many-Beziehungen nehme ich prefetch_related, das eine zweite Query absetzt und die Ergebnisse in Python zusammennäht. Nach dem Fix schreibe ich einen Test, der die View in assertNumQueries mit der erwarteten Zahl wickelt, denn sonst fügt der Nächste ein Template-Feld hinzu und es regressiert still. In einem internen Dashboard sind wir bei einer Seite von rund dreihundert Queries auf vier gekommen, und die Ladezeit ging von etwa zwei Sekunden auf unter zweihundert Millisekunden.
Steht dieses Vorstellungsgespräch bald an? GhostPilot hört bei deinem Live-Call mit, erkennt die Frage in dem Moment, in dem sie gestellt wird, und bringt dir eine strukturierte Antwort in Echtzeit auf den Bildschirm. Probier es im nächsten Mock aus, oder hol dir einen $29 Session Pass, kein Abo, für den Ernstfall.
So funktioniert esNachfragen, mit denen du rechnen solltest
- Wann ist prefetch_related langsamer als ein Join?
- Was ändern only und defer hier?
- Wie würdest du das im Code Review fangen?
Weitere Fragen für Python-Entwickler
Dein Interviewer stellt seine eigene Version davon. Kopier deine echte Stellenbeschreibung in den kostenlosen Question Predictor und bekomm die 20 Fragen, die diese Rolle am wahrscheinlichsten stellt, samt dem, worauf jede wirklich abzielt.
Meine Fragen vorhersagen