sql – Django:如何有效地使用带有Paginator的select_related()?

我有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相关.现在,我想获取一个包含5万个RnaPrecomputed项目的特定页面以及与之相关的相应Rnas.我期望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()表现良好?

最佳答案 值得检查的是,您没有错过数据库中的索引.对于Rna.upi字段,您有db_index = True,但是您确定数据库中存在索引吗?

如果select_related使count()查询变慢,那么您可以尝试在分页的object_list上执行select_related.

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