Djangos QuerySets effektiv nutzen

巴扎黑
Freigeben: 2017-04-05 15:05:57
Original
1938 Leute haben es durchsucht

Die objektrelationale Zuordnung (ORM) vereinfacht die Interaktion mit SQL-Datenbanken, gilt jedoch auch als ineffizient und langsamer als reines SQL.

Um ein ORM effektiv nutzen zu können, muss man verstehen, wie es die Datenbank abfragt. In diesem Artikel werde ich mich darauf konzentrieren, wie man das Django ORM-System effektiv nutzt, um auf mittlere bis große Datensätze zuzugreifen.

Djangos Abfragesatz ist faul

Djangos Abfragesatz entspricht mehreren Datensätzen (Zeilen) in der Datenbank, gefiltert durch optionale Abfragen. Mit dem folgenden Code werden beispielsweise alle Personen mit dem Namen „Dave“ in der Datenbank abgerufen:

person_set = Person.objects.filter(first_name="Dave")
Nach dem Login kopieren

Der obige Code führt keine Datenbankabfragen aus. Sie können person_set verwenden, einige Filterbedingungen hinzufügen oder es an eine Funktion übergeben, und diese Vorgänge werden nicht an die Datenbank gesendet. Dies ist richtig, da Datenbankabfragen einer der Faktoren sind, die die Leistung von Webanwendungen erheblich beeinflussen.

Um tatsächlich Daten aus der Datenbank zu erhalten, müssen Sie queryset durchlaufen:

for person in person_set:
    print(person.last_name)
Nach dem Login kopieren

Djangos Abfragesatz verfügt über einen Cache

Wenn Sie einen Abfragesatz durchlaufen, werden alle übereinstimmenden Datensätze aus der Datenbank abgerufen und in ein Django-Modell konvertiert. Dies nennt man Bewertung. Diese Modelle werden im integrierten Cache des Abfragesatzes gespeichert, sodass Sie bei einer erneuten Iteration durch den Abfragesatz nicht dieselbe allgemeine Abfrage erneut ausführen müssen.

Der folgende Code führt beispielsweise eine Datenbankabfrage nur einmal aus:

pet_set = Pet.objects.filter(species="Dog")
# The query is executed and cached.
for pet in pet_set:
    print(pet.first_name)
# The cache is used for subsequent iteration.
for pet in pet_set:
    print(pet.last_name)
Nach dem Login kopieren

Die if-Anweisung löst die Ausführung von queryset

aus Das Nützlichste am Abfragesatz-Cache ist, dass er effektiv testen kann, ob der Abfragesatz Daten enthält. Er wird nur durchlaufen, wenn Daten vorhanden sind:

restaurant_set = Restaurant.objects.filter(cuisine="Indian")
# `if`语句会触发queryset的执行。
if restaurant_set:
    # 遍历时用的是cache中的数据
    for restaurant in restaurant_set:
        print(restaurant.name)
Nach dem Login kopieren

Wenn Sie nicht alle Daten benötigen, kann der Queryset-Cache ein Problem sein

Manchmal möchten Sie vielleicht nur wissen, ob Daten vorhanden sind, ohne alle Daten zu durchlaufen. In diesem Fall führt die einfache Verwendung einer if-Anweisung zur Beurteilung dazu, dass der gesamte Abfragesatz vollständig ausgeführt und die Daten in den Cache gestellt werden, auch wenn Sie die Daten nicht benötigen!

city_set = City.objects.filter(name="Cambridge")
# `if`语句会执行queryset.。
if city_set:
    # 我们并不需要所有的数据,但是ORM仍然会获取所有记录!
    print("At least one city called Cambridge still stands!")
Nach dem Login kopieren

Um dies zu vermeiden, können Sie mit der Methode exist() prüfen, ob Daten vorhanden sind:

tree_set = Tree.objects.filter(type="deciduous")
# `exists()`的检查可以避免数据放入queryset的cache。
if tree_set.exists():
    # 没有数据从数据库获取,从而节省了带宽和内存
    print("There are still hardwood trees in the world!")
Nach dem Login kopieren

Wenn der Abfragesatz sehr groß ist, wird der Cache zum Problem

Bei der Verarbeitung von Tausenden von Datensätzen ist es verschwenderisch, sie alle auf einmal in den Speicher zu laden. Was noch schlimmer ist, ist, dass ein großer Abfragesatz den Systemprozess blockieren und Ihr Programm an den Rand eines Absturzes bringen kann.

Um zu vermeiden, dass beim Durchlaufen der Daten ein Queryset-Cache generiert wird, können Sie die Methode iterator() verwenden, um die Daten abzurufen und sie nach der Verarbeitung der Daten zu verwerfen.

star_set = Star.objects.all()
# `iterator()`可以一次只从数据库获取少量数据,这样可以节省内存
for star in star_set.iterator():
    print(star.name)
Nach dem Login kopieren

Die Verwendung der iterator()-Methode zur Verhinderung der Cache-Generierung bedeutet natürlich, dass Abfragen beim Durchlaufen desselben Abfragesatzes wiederholt ausgeführt werden. Seien Sie also vorsichtig, wenn Sie iterator() verwenden, und stellen Sie sicher, dass Ihr Code nicht wiederholt Abfragen ausführt, wenn er mit einem großen Abfragesatz arbeitet

Wenn der Abfragesatz groß ist, ist die if-Anweisung ein Problem

Wie bereits erwähnt, eignet sich der Queryset-Cache hervorragend zum Kombinieren von if-Anweisungen und for-Anweisungen, wodurch bedingte Schleifen für ein Queryset möglich sind. Für sehr große Abfragesätze ist das Caching von Abfragesätzen jedoch nicht geeignet.

Die einfachste Lösung besteht darin, exist() in Verbindung mit iterator() zu verwenden, um die Verwendung des Queryset-Cache durch die Verwendung von zwei Datenbankabfragen zu vermeiden.

molecule_set = Molecule.objects.all()
# One database query to test if any rows exist.
if molecule_set.exists():
    # Another database query to start fetching the rows in batches.
    for molecule in molecule_set.iterator():
        print(molecule.velocity)
Nach dem Login kopieren

Eine kompliziertere Lösung besteht darin, die „erweiterte Iterationsmethode“ von Python zu verwenden, um sich vor dem Starten der Schleife das erste Element von iterator() anzusehen und dann zu entscheiden, ob eine Schleife durchgeführt werden soll.

atom_set = Atom.objects.all()
# One database query to start fetching the rows in batches.
atom_iterator = atom_set.iterator()
# Peek at the first item in the iterator.
try:
    first_atom = next(atom_iterator)
except StopIteration:
    # No rows were found, so do nothing.
    pass
else:
    # At least one row was found, so iterate over
    # all the rows, including the first one.
    from itertools import chain
    for atom in chain([first_atom], atom_set):
        print(atom.mass)
Nach dem Login kopieren

Verhindern Sie unsachgemäße Optimierung

Der Cache von Queryset wird verwendet, um die Abfragen des Programms an die Datenbank zu reduzieren. Bei normaler Verwendung wird sichergestellt, dass die Datenbank nur bei Bedarf abgefragt wird.

Verwenden Sie die Methoden exist() und iterator(), um die Speichernutzung des Programms zu optimieren. Da sie jedoch keinen Queryset-Cache generieren, können sie zusätzliche Datenbankabfragen verursachen.

Sie müssen also beim Codieren aufpassen, wenn das Programm langsamer wird. Sie müssen prüfen, wo die Engpässe im Code liegen und ob es einige kleine Optimierungen gibt, die Ihnen helfen können.

Das obige ist der detaillierte Inhalt vonDjangos QuerySets effektiv nutzen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage