Heim >Backend-Entwicklung >Python-Tutorial >Suchen und beheben Sie Fehler in Django mithilfe von AppSignal

Suchen und beheben Sie Fehler in Django mithilfe von AppSignal

DDD
DDDOriginal
2024-12-22 21:10:39839Durchsuche

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!

Was sind N 1-Abfragen?

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.

Voraussetzungen

Stellen Sie sicher, dass Sie Folgendes haben:

  • Python 3.9 und Git auf Ihrem lokalen Computer installiert
  • Ein von AppSignal unterstütztes Betriebssystem
  • Ein AppSignal-Konto

Hinweis: Der Quellcode für dieses Projekt befindet sich im GitHub-Repository appsignal-django-n-plus-one.

Projekt-Setup

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

Installieren Sie AppSignal für Django

Um AppSignal in Ihrem Django-Projekt zu installieren, befolgen Sie die offiziellen Dokumente:

  • AppSignal Python-Installation
  • AppSignal Django-Instrumentierung
  • AppSignal SQLite-Instrumentierung

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.

Web-App-Logik

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.

Modelle

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.

Ansichten

Die Web-App stellt die folgenden Endpunkte bereit:

  1. /books/ gibt die Liste der Bücher zurück
  2. /books// gibt ein bestimmtes Buch zurück
  3. /books/by-authors/ gibt eine nach Autoren gruppierte Liste von Büchern zurück
  4. /books/authors/ gibt die Liste der Autoren zurück
  5. /books/authors// gibt einen bestimmten Autor zurück

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.

Erkennen Sie N 1-Abfragen in Ihrer Django-App mit AppSignal

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.

Erkennen Sie N 1 Abfragen in Ansichten

Besuchen Sie zunächst alle Endpunkte Ihrer App, um die Leistungsberichte zu erstellen:

  1. /books/
  2. /books//
  3. /books/by-authors/
  4. /books/authors/
  5. /books/authors//

Als nächstes verwenden wir das AppSignal-Dashboard, um langsame Endpunkte zu analysieren.

Beispiel 1: Eins-zu-Eins-Beziehung (select_lated())

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.

Find and Fix N ueries in Django Using AppSignal

Klicken Sie auf den langsamsten Endpunkt (books/), um dessen Details anzuzeigen.

Find and Fix N ueries in Django Using AppSignal

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.

Find and Fix N ueries in Django Using AppSignal

Scrollen Sie nach unten zur Ereigniszeitleiste, um zu sehen, welche SQL-Abfragen ausgeführt wurden.

Find and Fix N ueries in Django Using AppSignal

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.

Find and Fix N ueries in Django Using AppSignal

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.

Beispiel 2: Viele-zu-Eins-Beziehung (prefetch_lated())

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.

Erkennen Sie N 1-Abfragen in Django Admin

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:

Find and Fix N ueries in Django Using AppSignal

In meinem Fall sind die beiden langsamsten Endpunkte:

  1. /admin/login
  2. /admin/books/author/

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.

Zusammenfassung

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn