我有 2 个相关模型,每个模型有 1000 万行,并且想要对其中一个模型的 50000 个项目执行高效的分页请求,并访问另一个模型上的相关数据:
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)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,与通过外键RnaPrecomputed相关。现在,我想获取 50 000 个项目以及与它们相关的相应 sRNA的特定页面。如果我在不调用的情况下执行此操作,我预计会出现 N+1 请求问题。以下是时间安排:RnaPrecomputedRnaselect_related()
首先,作为参考,我根本不会碰相关模型:
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all(), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.id)
Run Code Online (Sandbox Code Playgroud)
需要:
real 0m12.614s
user 0m1.073s
sys 0m0.188s
Run Code Online (Sandbox Code Playgroud)
现在,我将尝试访问相关模型上的数据:
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all(), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.rna.upi)
Run Code Online (Sandbox Code Playgroud)
它需要:
real 2m27.655s
user 1m20.194s
sys 0m4.315s
Run Code Online (Sandbox Code Playgroud)
这是很多,所以,可能我有 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)
Run Code Online (Sandbox Code Playgroud)
还需要更多:
real 7m9.720s
user 0m1.948s
sys 0m0.337s
Run Code Online (Sandbox Code Playgroud)
所以,不知何故,select_related()事情没有变得更快,而是慢了三倍。可能没有它,我有 N+1 个请求,因此对于 的每个条目RnaPrecomputed,Django ORM 可能必须对数据库执行额外的请求以获取相应的Rna?
我做错了什么以及如何使select_related()分页查询集表现良好?
值得检查一下数据库中是否缺少索引。你有db_index=True该Rna.upi字段,但你确定该索引存在于数据库中吗?
如果 导致select_related查询变慢,那么您可以尝试在分页上count()执行。select_relatedobject_list
for object in rna_paginator.page(300).object_list.select_related():
message = message + str(object.rna.upi)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
827 次 |
| 最近记录: |