django中的Prefetch_related和select_related函数

django中的Prefetch_related和select_related函数

在Django中,select_related和prefetch_related被设计用来阻止因访问相关对象而导致的数据库查询的泛滥。在这篇文章中,我们将看到它是如何减少查询次数并使程序更快。

  • select_related() “遵循 “外键关系,当它执行查询时选择额外的相关对象数据。
  • prefetch_related()为每个关系做单独的查找,并在Python中做 “连接”。

当你要选择的对象是一个单一的对象时,就使用select_related,所以是OneToOneField或ForeignKey。当你要得到一个 “集合 “的东西时,你使用prefetch_related,所以像你说的ManyToManyFields或反向外键。澄清一下我说的 “反向外键 “是什么意思。

举例说明Prefetch_related和select_related的概念 –

上面的分类可能不是很清楚,让我们看一个例子。

class ModelA(models.Model):
   pass
 
class ModelB(models.Model):
   a = models.ForeignKey(ModelA, on_delete=models.CASCADE)
 
 
# Forward ForeignKey relationship
ModelB.objects.select_related('a').all()
 
# Reverse ForeignKey relationship
ModelA.objects.prefetch_related('modelb_set').all()

select_related通过多表连接协会查询一次获得所有数据,并通过减少数据库查询次数提高性能。它使用SQL的JOIN语句,通过减少SQL查询的次数来优化和提高性能。后者是通过JOIN语句来解决SQL查询中的问题。但是,对于多对多的关系,使用SQL语句来解决是不明智的,因为通过JOIN得到的表会很长,这将导致SQL语句的运行时间和内存占用增加。解决prefetch_related()的方法是分别查询每个表,然后用Python来处理它们之间的关系!

这里有一些例子。

Models.py的内容如下。

from django.db import models
 
class Province(models.Model):
   name = models.CharField(max_length = 10)
   def __unicode__(self):
       return self.name
 
class City(models.Model):
   name = models.CharField(max_length = 5)
   province = models.ForeignKey(Province)
   def __unicode__(self):
       return self.name
 
class Person(models.Model):
   firstname = models.CharField(max_length = 10)
   lastname = models.CharField(max_length = 10)
   visitation = models.ManyToManyField(City, related_name = "visitor")
   hometown = models.ForeignKey(City, related_name = "birth")
   living = models.ForeignKey(City, related_name = "citizen")
   def __unicode__(self):
       return self.firstname + self.lastname

select_related –

我们使用select_related()函数。

>>> citys = City.objects.select_related().all()
>>> for c in citys:
...   print c.province
...

只有一个SQL查询,这显然大大减少了SQL查询的数量。

SELECT `Optimize_city`.`id`, `Optimize_city`.`name`,
`Optimize_city`.`province_id`, `Optimize_province`.`id`, `Optimize_province`.`name`
FROM`Optimize_city`
INNER JOIN `Optimize_province` ON
(`Optimize_city`.`province_id`=`Optimize_province`.`id`);

prefetch_related –

这里我们可以看到,Django使用了INNER JOIN。我想明确一点,Optimize是我们应用程序的一个名称。如果我们想得到湖北的所有城市名称,我们可以这样做。

> HB=Province.objects.prefetch_related('city_set').get(name__iexact=u"Hubei Province")
>>> for city in hb.city_set.all():
...   city.name
...

触发的SQL查询。

SELECT `Optimize_province`.`id`, `Optimize_province`.`name`
FROM `Optimize_province`
WHERE `Optimize_province', `name `LIKE'Hubei Province';

SELECT `Optimize_city`.`id`, `Optimize_city`.`name`, `Optimize_city`.`province_id`
FROM `Optimize_city`
WHERE `Optimize_city`.`province_id` IN (1);

我们可以看到,预取是使用IN语句实现的。这样,当QuerySet中有太多的对象时,根据数据库的特点,可能会出现性能问题。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

Django 教程