在 Django 中优化查询,prefact_related 用于反向链接的对象
Optimizing queries in Django, prefact_related for objects that are reversely linked
在我的 django 项目中,我有 3 个模型,针对此示例进行了简化:Contact、WorkRelation 和 Group 对象。
联系
class Contact(BaseModel):
title = models.CharField(max_length=30, blank=True)
initials = models.CharField(max_length=10, blank=True)
first_name = models.CharField(max_length=30, blank=True)
prefix = models.CharField(max_length=20, blank=True)
surname = models.CharField(max_length=30)
def get_workrelations(self):
workrelations = apps.get_model('groups', 'WorkRelation')
return workrelations.objects.filter(contact=self)
def get_organisations(self):
output = ""
strings = []
wr = self.get_workrelations()
for relation in wr:
group = relation.group
name = group.name
strings.append(s)
if len(strings) > 0:
output = ", ".join(strings)
return output
工作关系
class WorkRelation(BaseModel):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
function = models.CharField(max_length=40, blank=True)
email_address = models.EmailField()
phone_number = models.CharField(max_length=13, blank=True)
description = models.TextField(max_length=400, blank=True)
组
class Group(BaseModel):
group_type = models.ForeignKey(GroupType, on_delete=models.CASCADE)
name = models.CharField(max_length=60, unique=True)
street_name = models.CharField(max_length=40, blank=True)
house_number = models.CharField(max_length=10, blank=True)
此设置的问题是,当我想在大型联系人集上调用 get_organisations() 时,它会变得非常慢。例如:当尝试列出我所有的联系人(我的演示集有 600 个)并调用 get_organisations() 时,大约需要 1250 个查询。
我发现您可以使用 prefetch_data() 来防止这种情况发生,但不知何故我无法在我的设置中使用它。我试图替换我对
的查询
queryset = Contact.objects.prefetch_related('workrelation_set')
但这并没有加快速度(与我的推测相反)。你们知道是否有可能加快速度吗?
将您的 get_organisations 代码更改为:
def get_organisations(self):
return ', '.join(
workrelation.group.name for workrelation
in self.workrelation_set.all()
)
并使用此查询获取联系人对象:
Contact.objects.prefetch_related('workrelation_set__group')
这将 return 单个查询的结果。
在我的 django 项目中,我有 3 个模型,针对此示例进行了简化:Contact、WorkRelation 和 Group 对象。
联系
class Contact(BaseModel):
title = models.CharField(max_length=30, blank=True)
initials = models.CharField(max_length=10, blank=True)
first_name = models.CharField(max_length=30, blank=True)
prefix = models.CharField(max_length=20, blank=True)
surname = models.CharField(max_length=30)
def get_workrelations(self):
workrelations = apps.get_model('groups', 'WorkRelation')
return workrelations.objects.filter(contact=self)
def get_organisations(self):
output = ""
strings = []
wr = self.get_workrelations()
for relation in wr:
group = relation.group
name = group.name
strings.append(s)
if len(strings) > 0:
output = ", ".join(strings)
return output
工作关系
class WorkRelation(BaseModel):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
function = models.CharField(max_length=40, blank=True)
email_address = models.EmailField()
phone_number = models.CharField(max_length=13, blank=True)
description = models.TextField(max_length=400, blank=True)
组
class Group(BaseModel):
group_type = models.ForeignKey(GroupType, on_delete=models.CASCADE)
name = models.CharField(max_length=60, unique=True)
street_name = models.CharField(max_length=40, blank=True)
house_number = models.CharField(max_length=10, blank=True)
此设置的问题是,当我想在大型联系人集上调用 get_organisations() 时,它会变得非常慢。例如:当尝试列出我所有的联系人(我的演示集有 600 个)并调用 get_organisations() 时,大约需要 1250 个查询。
我发现您可以使用 prefetch_data() 来防止这种情况发生,但不知何故我无法在我的设置中使用它。我试图替换我对
的查询queryset = Contact.objects.prefetch_related('workrelation_set')
但这并没有加快速度(与我的推测相反)。你们知道是否有可能加快速度吗?
将您的 get_organisations 代码更改为:
def get_organisations(self):
return ', '.join(
workrelation.group.name for workrelation
in self.workrelation_set.all()
)
并使用此查询获取联系人对象:
Contact.objects.prefetch_related('workrelation_set__group')
这将 return 单个查询的结果。