Optimierung von Django ORM-Abfragen

Django ORM macht die Datenbankarbeit einfach. Aber es birgt eine Gefahr. Wenn Sie verwandte Objekte ineffizient abrufen, erzeugen Sie das N+1-Abfrageproblem.

Das bedeutet: Wenn Sie 100 Beiträge abrufen, führt Ihre App möglicherweise 101 Abfragen aus. Dies bremst Ihre Anwendung massiv aus.

Nutzen Sie diese zwei Werkzeuge, um das Problem zu beheben:

  1. select_related

Verwenden Sie dies für ForeignKey und OneToOneField.

Es nutzt einen SQL JOIN. Dadurch werden die verwandten Daten in einer einzigen Abfrage abgerufen.

  • Beispiel: Ein Post hat einen Author.
  • Naive Vorgehensweise: 101 Abfragen für 100 Beiträge.
  • Optimierte Vorgehensweise: 1 Abfrage mit .select_related("author").
  1. prefetch_related

Verwenden Sie dies für ManyToManyField und umgekehrte ForeignKeys.

Es führt separate Abfragen aus und führt diese in Python zusammen.

  • Beispiel: Ein Post hat viele Tags.
  • Naive Vorgehensweise: 1 Abfrage für die Beiträge + 1 Abfrage für die Tags jedes einzelnen Beitrags.
  • Optimierte Vorgehensweise: Insgesamt 2 Abfragen mit .prefetch_related("tags").

Pro-Tipps:

  • Verwenden Sie das Prefetch-Objekt, um verwandte Daten zu filtern, bevor sie in Ihre Schleife gelangen.
  • Verketten Sie diese. Sie können beide in einem einzigen Queryset verwenden, um Autoren und Tags gleichzeitig abzurufen.
  • Vermeiden Sie es, .filter() innerhalb einer Schleife auf eine mit prefetch_related geladene Beziehung aufzurufen. Dies umgeht den Cache und führt zu einer erneuten Datenbankabfrage.
  • Verwenden Sie .only() zusammen mit select_related, um nur die Spalten abzurufen, die Sie tatsächlich benötigen.

Zusammenfassung:

  • ForeignKey / OneToOne: Verwenden Sie select_related.
  • ManyToMany / Reverse FK: Verwenden Sie prefetch_related.

Überprüfen Sie Ihre Abfrageanzahl mit django-debug-toolbar, um solche Probleme frühzeitig zu erkennen.

Quelle: https://dev.to/fhva29/optimizing-django-orm-queries-a-practical-guide-to-selectrelated-and-prefetchrelated-1gpl