Ausgabe
Im Django-Dokument,
select_related()
“folgt” Fremdschlüsselbeziehungen und wählt zusätzliche zugehörige Objektdaten aus, wenn es seine Abfrage ausführt.
prefetch_related()
führt für jede Beziehung eine separate Suche durch und führt das “Joining” in Python durch.
Was bedeutet es, “die Verbindung in Python zu machen”? Kann das jemand anhand eines Beispiels veranschaulichen?
Mein Verständnis ist, dass für Fremdschlüsselbeziehungen select_related
; und für M2M-Beziehungen verwenden Sie prefetch_related
. Ist das richtig?
Lösung
Ihr Verständnis ist größtenteils richtig. Sie verwenden, select_related
wenn das Objekt, das Sie auswählen werden, ein einzelnes Objekt ist, so OneToOneField
oder eine ForeignKey
. Sie verwenden, prefetch_related
wenn Sie einen “Satz” von Dingen erhalten möchten, also ManyToManyField
s, wie Sie es angegeben haben, oder kehren Sie ForeignKey
s um. Nur um zu verdeutlichen, was ich mit “umgekehrten ForeignKey
s” meine, hier ein Beispiel:
class ModelA(models.Model):
pass
class ModelB(models.Model):
a = ForeignKey(ModelA)
ModelB.objects.select_related('a').all() # Forward ForeignKey relationship
ModelA.objects.prefetch_related('modelb_set').all() # Reverse ForeignKey relationship
Der Unterschied besteht darin, dass select_related
ein SQL-Join ausgeführt wird und die Ergebnisse daher als Teil der Tabelle vom SQL-Server zurückerhalten werden. prefetch_related
führt dagegen eine andere Abfrage aus und reduziert damit die redundanten Spalten im Originalobjekt ( ModelA
im obigen Beispiel). Sie können prefetch_related
für alles verwenden, was Sie verwenden können select_related
.
Die Kompromisse bestehen darin prefetch_related
, dass eine Liste von IDs erstellt und an den Server zurückgesendet werden muss, was eine Weile dauern kann. Ich bin mir nicht sicher, ob es eine nette Möglichkeit gibt, dies in einer Transaktion zu tun, aber ich verstehe, dass Django immer nur eine Liste sendet und sagt SELECT … WHERE pk IN (…,…,…) Grundsätzlich. In diesem Fall, wenn die vorab abgerufenen Daten spärlich sind (sagen wir, US-Staatsobjekte, die mit den Adressen von Personen verknüpft sind), kann dies sehr gut sein, aber wenn es näher an einer Eins-zu-Eins-Daten ist, kann dies viel Kommunikation verschwenden. Probieren Sie im Zweifelsfall beide aus und sehen Sie, was besser funktioniert.
Alles, was oben besprochen wurde, dreht sich im Wesentlichen um die Kommunikation mit der Datenbank. Auf der Python-Seite hat es jedoch prefetch_related
den zusätzlichen Vorteil, dass ein einzelnes Objekt verwendet wird, um jedes Objekt in der Datenbank darzustellen. Mit select_related
doppelten Objekten werden in Python für jedes “übergeordnete” Objekt erstellt. Da Objekte in Python einen ordentlichen Speicheraufwand haben, kann dies auch eine Überlegung sein.
Beantwortet von – CrazyCasta
Antwort geprüft von – Timothy Miller (FixError Admin)