Ich habe 2 verwandte Modelle mit 10 Millionen Zeilen je und will eine effiziente paginierte Anfrage von 50 000 Stück von einem von ihnen und dem Zugang bezogenen Daten auf dem anderen auszuführen:Django: Wie effektiv select_related() mit Paginator verwenden?
class RnaPrecomputed(models.Model):
id = models.CharField(max_length=22, primary_key=True)
rna = models.ForeignKey('Rna', db_column='upi', to_field='upi', related_name='precomputed')
description = models.CharField(max_length=250)
class Rna(models.Model):
id = models.IntegerField(db_column='id')
upi = models.CharField(max_length=13, db_index=True, primary_key=True)
timestamp = models.DateField()
userstamp = models.CharField(max_length=30)
Wie Sie sehen, können RnaPrecomputed
bezieht sich auf RNA
über einen Fremdschlüssel. Jetzt möchte ich eine bestimmte Seite von 50 000 Artikeln von RnaPrecomputed
und entsprechenden Rna
s bezogen auf sie beziehen. Ich erwarte N + 1 Anfragen Problem, wenn ich dies ohne select_related()
Anruf mache. Hier sind die Timings:
Zuerst Referenz werde ich nicht das entsprechende Modell berühren überhaupt:
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all(), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.id)
Takes:
real 0m12.614s
user 0m1.073s
sys 0m0.188s
Nun, ich Versuchen Sie, auf Daten zu verwandten Modellen zuzugreifen:
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all(), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.rna.upi)
es braucht:
real 2m27.655s
user 1m20.194s
sys 0m4.315s
was viel ist, so, wahrscheinlich habe ich N + 1-Anfragen Problem.
Aber jetzt, wenn ich select_related()
,
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all().select_related('rna'), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.rna.upi)
dauert es noch mehr:
real 7m9.720s
user 0m1.948s
sys 0m0.337s
Also, irgendwie select_related()
Dinge 3 mal langsamer gemacht, anstatt sie schneller zu machen. Und wahrscheinlich ohne es, ich habe N + 1 Anfragen, so für jeden Eintrag von RnaPrecomputed
, muss Django ORM wahrscheinlich eine zusätzliche Anfrage an die Datenbank zu holen, um die entsprechenden Rna
?
Was mache ich falsch und wie macht man select_related()
mit paginiertem Queryset gut?
Es wäre nützlich zu sehen, was die Abfragen sind und wie lange sie dauern, anstatt die Gesamtzeit. – Alasdair
@Alasdair Danke für Interesse. Ich bin bereit, Informationen zur Verfügung zu stellen, die Sie verlangen, aber nicht sicher, was Sie genau meinen. Sprechen Sie über SQL-Anfragen? –
Ja, die SQL-Abfragen. Sie können hierfür die Django Debug-Symbolleiste oder 'connection.queries' verwenden. – Alasdair