我有2個相關的模型擁有1000萬行,每行和要執行的50 000項其中之一,並獲得相關數據的另一種高效的分頁請求:Django:如何有效地使用select_related()和Paginator?
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)
正如你所看到的,RnaPrecomputed
通過外鍵與RNA
相關。現在,我想獲取與他們相關的特定頁面的50000個項目RnaPrecomputed
和相應的Rna
。我期望N + 1請求的問題,如果我沒有select_related()
的呼叫。這裏是計時:
首先,僅供參考我不會接觸到相關的模型都:
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all(), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.id)
注意到:
real 0m12.614s
user 0m1.073s
sys 0m0.188s
現在的我,將嘗試訪問相關型號的數據:
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all(), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.rna.upi)
需要:
real 2m27.655s
user 1m20.194s
sys 0m4.315s
這是很多,所以,也許我有N + 1的要求的問題。
但現在,如果我用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)
它需要更:
real 7m9.720s
user 0m1.948s
sys 0m0.337s
所以,在某種程度上select_related()
做事情慢3倍,而不是讓他們更快。可能沒有它,我有N + 1個請求,所以對於RnaPrecomputed
的每個條目,Django ORM可能需要額外請求數據庫以獲取相應的Rna
?
我在做什麼錯誤以及如何使select_related()
在分頁查詢集中表現良好?
查看查詢的內容以及查詢時長,而不是整個時間,這將會非常有用。 – Alasdair
@Alasdair感謝您的關注。我願意提供您請求的信息,但不確定,您的意思到底是什麼。你在說SQL請求嗎? –
是的,SQL查詢。您可以使用Django Debug工具欄或'connection.queries'來執行此操作。 – Alasdair