Die Anzahl der Django-Projekte im Unternehmen nimmt zu, und die Anzahl der uncoolen Abfragen wird wahrscheinlich zunehmen. Hinterlassen Sie daher einfach eine Notiz.
Verwenden Sie prefetch_related, da es katastrophal wäre, die Abfrage jedes Mal zu überspringen, wenn Sie eine Schleife ausführen, wenn Sie die umgekehrte Referenz des Fremdschlüssels abrufen oder das Referenzziel von Many-to-Many abrufen, ohne über die Verwendung von ORM nachzudenken. Die Geschichte des Schmelzens
Wenn es sich um einen normalen Fremdschlüssel handelt, können Sie ihn mit select_related durch die erforderliche Hierarchie ziehen.
Ein solches Modell vorerst
from django.db import models
class Campaign(models.Model):
name = models.CharField(max_length=255)
created_at = models.DateTimeField()
class Creative(models.Model):
name = models.CharField(max_length=255, default="")
campaign = models.ForeignKey(Campaign)
created_at = models.DateTimeField()
Wenn Sie Campaign von Creative subtrahieren möchten, können Sie select_related verwenden, um Campaign beizutreten und abzurufen, ohne es bei jeder Schleife auszuwählen.
for creative in Creative.objects.all().select_related():
print(creative.campaign)
Verwenden Sie prefetch_related, um die Liste der Motive aus der Kampagne abzurufen
for campaign in Campaign.objects.all().prefetch_related("creative_set"):
print(campaign.creative_set.all())
Es scheint, dass alle Kampagnen einmal gezogen werden, anstatt beizutreten, und die Liste der Kampagne.id wird dort eingezogen, wo sie sich befindet. Nun, es ist besser als jedes Mal zu fliegen, und in den meisten Fällen scheint es kein Problem zu sein.
Das Eingrenzen der Kampagne mit Creative erfolgt übrigens normalerweise mit einer Abfrage
Campaign.object.filter(creative_set__name="aaa")
Wenn Sie einfach prefetch_related verwenden, können Sie nur das Ding von XXXX_set.all () erhalten. Wenn Sie das creative_set eingrenzen, wird die Abfrage bei jeder Schleife ausgeführt, was Sie sehr traurig macht.
for campaign in Campaign.objects.all().prefetch_related("creative_set"):
print(campaign.creative_set.filter(name__startswith="hoge"))
Wenn Sie das Ziel der umgekehrten Referenz oder von Many-to-Many mithilfe eines Filters eingrenzen oder die Reihenfolge angeben möchten, verwenden Sie das Prefetch-Objekt aus 1.7 von Django. Dank dieses Typen habe ich das Gefühl, dass sich Djangos ORM stark verbessert hat.
from django.db import models
from django.db.models import Prefetch
for campaign in Campaign.objects.all().prefetch_related(Prefetch("creative_set", queryset=Creative.objects.filter(name__startswith="hoge").order_by("-created_at"), to_attr="creatives")):
if len(campaign.creatives) > 0:
print(campaign.id, creatives[0].id)
Unabhängig davon, wie viele Kampagnen Sie haben, müssen Sie die Abfrage nur zweimal überspringen.
Wenn Sie eine Abfrage optimieren, werden Sie wahrscheinlich die Django-Shell verwenden, um die Abfrage zu überprüfen. Es ist daher eine gute Idee, sich mit dem Logger herumzuschlagen, damit die SQL-Anweisung angezeigt wird, wenn Sie die Abfrage mit der Shell treffen. Ich denke, dass ich mit den Protokolleinstellungen herumspiele, wenn ich es normal mache, aber ich bin froh, wenn ich die Protokollstufe von django.db.backends nur bei der Untersuchung von Abfragen auf DEBUG setze.
settings.py
LOGGING = {
'version': 1,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
}
},
'loggers': {
'django.db.backends': {
'level': 'DEBUG',
'handlers': ['console'],
},
}
}
Für die Optimierung nach Ansicht ist es einfach, die Abfrage mithilfe der django-debug-Symbolleiste zu überprüfen.
Recommended Posts