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 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")
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)
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)
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)
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!")
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!")
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)
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
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)
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)
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!