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:
- 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").
- 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.