我有2个相关模型,每个模型有1000万行,并希望对其中一个项目中的50 000个项目执行有效的分页请求,并在另一个上访问相关数据:
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
相关。现在,我想获取一个包含50 000项RnaPrecomputed
项和与之相关的Rna
项的特定页面。如果我没有select_related()
调用,我希望N + 1请求有问题。以下是时间安排:
首先,作为参考,我根本不会触及相关模型:
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()
在分页查询集中表现良好?
答案 0 :(得分:1)
值得检查一下,您没有错过数据库中的索引。 db_index=True
字段有Rna.upi
,但您确定数据库中存在索引吗?
如果select_related
使count()
查询变慢,那么您可以尝试在分页select_related
上执行object_list
。
for object in rna_paginator.page(300).object_list.select_related():
message = message + str(object.rna.upi)