Django:如何有效地将select_related()与Paginator一起使用?



>我有 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。我希望 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()在分页查询集中表现良好?

值得检查的是,数据库中是否缺少索引。您db_index=TrueRna.upi字段,但您确定数据库中存在索引吗?

如果select_related使count()查询变慢,则可以尝试对分页object_list执行select_related

for object in rna_paginator.page(300).object_list.select_related():
message = message + str(object.rna.upi)

最新更新