Heim >Backend-Entwicklung >Python-Tutorial >Suchen und beheben Sie Fehler in Django mithilfe von AppSignal
In diesem Artikel erfahren Sie mehr über N 1-Abfragen, wie Sie sie mit AppSignal erkennen und wie Sie sie beheben können, um Ihre Django-Apps erheblich zu beschleunigen.
Wir beginnen mit den theoretischen Aspekten und gehen dann zu praktischen Beispielen über. Die praktischen Beispiele spiegeln Szenarien wider, denen Sie in einer Produktionsumgebung begegnen könnten.
Lasst uns anfangen!
Das N 1-Abfrageproblem ist ein weit verbreitetes Leistungsproblem in Webanwendungen, die mit einer Datenbank interagieren. Diese Abfragen können zu erheblichen Engpässen führen, die sich mit zunehmender Datenbankgröße verstärken.
Das Problem tritt auf, wenn Sie eine Sammlung von Objekten abrufen und dann auf die zugehörigen Objekte für jedes Element in der Sammlung zugreifen. Das Abrufen einer Liste von Büchern erfordert beispielsweise eine einzelne Abfrage (1 Abfrage), aber der Zugriff auf den Autor für jedes Buch löst eine zusätzliche Abfrage für jedes Element aus (N Abfragen).
N 1 Probleme können auch beim Erstellen oder Aktualisieren von Daten in einer Datenbank auftreten. Wenn Sie beispielsweise eine Schleife durchlaufen, um Objekte einzeln zu erstellen oder zu aktualisieren, anstatt Methoden wie bulk_create() oder bulk_update() zu verwenden, kann dies zu übermäßigen Abfragen führen.
N 1 Abfragen sind äußerst ineffizient, da die Ausführung zahlreicher kleiner Abfragen deutlich langsamer und ressourcenintensiver ist als die Konsolidierung von Vorgängen in weniger, größeren Abfragen.
Djangos standardmäßiges QuerySet-Verhalten kann unbeabsichtigt zu N 1-Problemen führen, insbesondere wenn Sie nicht wissen, wie QuerySets funktionieren. Abfragesätze in Django sind verzögert, was bedeutet, dass keine Datenbankabfragen ausgeführt werden, bis der QuerySet ausgewertet ist.
Stellen Sie sicher, dass Sie Folgendes haben:
Hinweis: Der Quellcode für dieses Projekt befindet sich im GitHub-Repository appsignal-django-n-plus-one.
Wir arbeiten mit einer Buchverwaltungs-Web-App. Die Web-App wurde entwickelt, um das N 1-Abfrageproblem und seine Lösung zu demonstrieren.
Klonen Sie zunächst den Basiszweig des GitHub-Repos:
$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \ --single-branch --branch base && cd appsignal-django-n-plus-one
Als nächstes erstellen und aktivieren Sie eine virtuelle Umgebung:
$ python3 -m venv venv && source venv/bin/activate
Installieren Sie die Anforderungen:
(venv)$ pip install -r requirements.txt
Migrieren und füllen Sie die Datenbank:
(venv)$ python manage.py migrate (venv)$ python manage.py populate_db
Zuletzt starten Sie den Entwicklungsserver:
(venv)$ python manage.py runserver
Öffnen Sie Ihren bevorzugten Webbrowser und navigieren Sie zu http://localhost:8000/books. Die Web-App sollte eine JSON-Liste mit 500 Büchern aus der Datenbank zurückgeben.
Die Django-Administratorseite ist unter http://localhost:8000/admin zugänglich. Die Administrator-Anmeldeinformationen lauten:
user: username pass: password
Um AppSignal in Ihrem Django-Projekt zu installieren, befolgen Sie die offiziellen Dokumente:
Stellen Sie sicher, dass alles funktioniert, indem Sie den Entwicklungsserver neu starten:
$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \ --single-branch --branch base && cd appsignal-django-n-plus-one
Ihre App sollte automatisch einen Demo-Fehler an AppSignal senden. Ab diesem Zeitpunkt werden alle Ihre Fehler an AppSignal gesendet. Darüber hinaus überwacht AppSignal die Leistung Ihrer App und erkennt etwaige Probleme.
Die Voraussetzung für die Behebung von N 1-Abfragen ist das Verständnis des Datenbankschemas Ihrer App. Achten Sie genau auf die Beziehungen Ihrer Models: Sie können Ihnen dabei helfen, potenzielle N-1-Probleme zu erkennen.
Die Web-App verfügt über zwei Modelle – Autor und Buch –, die eine Eins-zu-Viele-Beziehung (1:M) teilen. Das bedeutet, dass jedes Buch einem einzelnen Autor zugeordnet ist, während ein Autor mit mehreren Büchern verknüpft werden kann.
Beide Modelle verfügen über eine to_dict()-Methode zum Serialisieren von Modellinstanzen in JSON. Darüber hinaus verwendet das Buchmodell eine umfassende Serialisierung (Serialisierung des Buches sowie des Buchautors).
Die Modelle sind in Books/models.py definiert:
$ python3 -m venv venv && source venv/bin/activate
Sie werden dann für die Django-Administratorseite in Books/admin.py registriert, etwa so:
(venv)$ pip install -r requirements.txt
Beachten Sie, dass AuthorAdmin BookInline verwendet, um die Bücher des Autors auf der Admin-Seite des Autors anzuzeigen.
Die Web-App stellt die folgenden Endpunkte bereit:
Die obigen Links können angeklickt werden, wenn der Entwicklungs-Webserver ausgeführt wird.
Und sie sind in Books/views.py wie folgt definiert:
(venv)$ python manage.py migrate (venv)$ python manage.py populate_db
Großartig, Sie wissen jetzt, wie die Web-App funktioniert!
Im nächsten Abschnitt vergleichen wir unsere App mit AppSignal, um N 1-Anfragen zu erkennen, und ändern dann den Code, um sie zu eliminieren.
Leistungsprobleme mit AppSignal zu erkennen ist einfach. Sie müssen die App lediglich wie gewohnt verwenden/testen (z. B. Endbenutzertests durchführen, indem Sie alle Endpunkte besuchen und die Antworten validieren).
Wenn ein Endpunkt erreicht wird, erstellt AppSignal einen Leistungsbericht dafür und gruppiert alle zugehörigen Besuche. Jeder Besuch wird als Probe im Bericht des Endpunkts aufgezeichnet.
Besuchen Sie zunächst alle Endpunkte Ihrer App, um die Leistungsberichte zu erstellen:
Als nächstes verwenden wir das AppSignal-Dashboard, um langsame Endpunkte zu analysieren.
Navigieren Sie zu Ihrer AppSignal-App und wählen Sie Leistung > Problemliste in der Seitenleiste. Klicken Sie dann auf Mittelwert, um die Probleme nach absteigender mittlerer Antwortzeit zu sortieren.
Klicken Sie auf den langsamsten Endpunkt (books/), um dessen Details anzuzeigen.
Wenn wir uns das neueste Beispiel ansehen, können wir sehen, dass dieser Endpunkt in 1090 Millisekunden eine Antwort zurückgibt. Die Gruppenaufteilung zeigt, dass SQLite 651 Millisekunden benötigt, während Django 439 benötigt.
Dies weist auf ein Problem hin, da ein so einfacher Endpunkt nicht so lange dauern sollte.
Um weitere Details darüber zu erhalten, was passiert ist, wählen Sie in der Seitenleiste Beispiele und dann das neueste Beispiel aus.
Scrollen Sie nach unten zur Ereigniszeitleiste, um zu sehen, welche SQL-Abfragen ausgeführt wurden.
Wenn Sie mit der Maus über den Text „query.sql“ fahren, wird die eigentliche SQL-Abfrage angezeigt.
Mehr als 1000 Abfragen wurden ausgeführt:
$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \ --single-branch --branch base && cd appsignal-django-n-plus-one
Dies sind ein klares Zeichen für N 1-Anfragen. Die erste Abfrage hat ein Buch abgerufen (1), und jede weitere Abfrage hat die Details des Autors des Buchs abgerufen (N).
Um das Problem zu beheben, navigieren Sie zu Books/views.py und ändern Sie book_list_view() wie folgt:
$ python3 -m venv venv && source venv/bin/activate
Durch die Verwendung der Methode select_lated() von Django wählen wir die zusätzlichen zugehörigen Objektdaten (d. h. den Autor) in der ersten Abfrage aus. Der ORM nutzt nun einen SQL-Join und die endgültige Abfrage sieht etwa so aus:
(venv)$ pip install -r requirements.txt
Warten Sie, bis der Entwicklungsserver neu gestartet ist, und testen Sie den betroffenen Endpunkt erneut.
Nach einem erneuten Benchmarking steigt die Antwortzeit von 1090 auf 45 und die Anzahl der Abfragen sinkt von 1024 auf 2. Dies ist eine Verbesserung um das 24-fache bzw. 512-fache.
Als nächstes schauen wir uns den zweitlangsamsten Endpunkt an (Bücher/Autoren/).
Verwenden Sie das Dashboard wie im vorherigen Schritt, um die SQL-Abfragen des Endpunkts zu überprüfen. Sie werden bei diesem Endpunkt ein ähnliches, aber weniger schwerwiegendes N 1-Muster bemerken.
Die Leistung dieses Endpunkts ist weniger schwerwiegend, da Django intelligent genug ist, um die häufig ausgeführten SQL-Abfragen zwischenzuspeichern, d. h. den Autor eines Buchs wiederholt abzurufen. Schauen Sie sich die offiziellen Dokumente an, um mehr über Django-Caching zu erfahren.
Lassen Sie uns prefetch_lated() in Books/views.py verwenden, um den Endpunkt zu beschleunigen:
$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \ --single-branch --branch base && cd appsignal-django-n-plus-one
Im vorherigen Abschnitt haben wir die Methode select_lated() verwendet, um eine Eins-zu-Eins-Beziehung zu verarbeiten (jedes Buch hat einen einzelnen Autor). In diesem Fall handelt es sich jedoch um eine Eins-zu-viele-Beziehung (ein Autor kann mehrere Bücher haben), daher müssen wir prefetch_lated() verwenden.
Der Unterschied zwischen diesen beiden Methoden besteht darin, dass select_lated() auf der SQL-Ebene arbeitet, während prefetch_lated() auf der Python-Ebene optimiert. Die letztere Methode kann auch für Viele-zu-Viele-Beziehungen verwendet werden.
Weitere Informationen finden Sie in den offiziellen Dokumenten von Django zu prefetch_lated().
Nach dem Benchmarking steigt die Antwortzeit von 90 auf 44 Millisekunden und die Anzahl der Abfragen sinkt von 32 auf 4.
Das Erkennen von N 1-Abfragen auf der Django-Administratorseite funktioniert ähnlich.
Melden Sie sich zunächst auf Ihrer Admin-Site an und erstellen Sie Leistungsberichte (erstellen Sie beispielsweise einige Autoren oder Bücher, aktualisieren und löschen Sie sie).
Navigieren Sie als Nächstes zu Ihrem AppSignal-App-Dashboard und filtern Sie die Probleme dieses Mal nach Administrator:
In meinem Fall sind die beiden langsamsten Endpunkte:
Wir können nicht viel gegen /admin/login unternehmen, da es vollständig von Django verwaltet wird. Konzentrieren wir uns also auf den zweitlangsamsten Endpunkt. Bei der Untersuchung wird ein N 1-Abfrageproblem aufgedeckt. Der Autor wird für jedes Buch separat abgefragt.
Um dies zu beheben, überschreiben Sie get_queryset() in BookInline, um Autorendetails in der ersten Abfrage abzurufen:
$ python3 -m venv venv && source venv/bin/activate
Machen Sie noch einmal einen Vergleich und stellen Sie sicher, dass die Anzahl der Abfragen zurückgegangen ist.
In diesem Beitrag haben wir das Erkennen und Beheben von N 1-Abfragen in Django mithilfe von AppSignal besprochen.
Die Nutzung dessen, was Sie hier gelernt haben, kann Ihnen dabei helfen, Ihre Django-Webanwendungen erheblich zu beschleunigen.
Die beiden wichtigsten Methoden, die Sie im Auge behalten sollten, sind select_lated() und prefetch_lated(). Die erste wird für Eins-zu-eins-Beziehungen verwendet, die zweite für Eins-zu-viele- und Viele-zu-viele-Beziehungen.
Viel Spaß beim Codieren!
P.S. Wenn Sie Python-Beiträge lesen möchten, sobald sie veröffentlicht werden, abonnieren Sie unseren Python Wizardry-Newsletter und verpassen Sie keinen einzigen Beitrag!
Das obige ist der detaillierte Inhalt vonSuchen und beheben Sie Fehler in Django mithilfe von AppSignal. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!