首页 > 编程 > Python > 正文

Python的Django框架中的select_related函数对QuerySet 查询的优化

2020-02-23 00:30:25
字体:
来源:转载
供稿:网友

1. 实例的背景说明

假定一个个人信息系统,需要记录系统中各个人的故乡、居住地、以及到过的城市。数据库设计如下:

201541150650059.jpg (591×250)

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

注1:创建的app名为“QSOptimize”

注2:为了简化起见,`qsoptimize_province` 表中只有2条数据:湖北省和广东省,`qsoptimize_city`表中只有三条数据:武汉市、十堰市和广州市
2. select_related()

对于一对一字段(OneToOneField)和外键字段(ForeignKey),可以使用select_related 来对QuerySet进行优化
作用和方法

在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在之后需要的时候不必再查询数据库了。以上例说明,如果我们需要打印数据库中的所有市及其所属省份,最直接的做法是:
 

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

这样会导致线性的SQL查询,如果对象数量n太多,每个对象中有k个外键字段的话,就会导致n*k+1次SQL查询。在本例中,因为有3个city对象就导致了4次SQL查询:
 

SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`FROM `QSOptimize_city` SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`FROM `QSOptimize_province`WHERE `QSOptimize_province`.`id` = 1 ; SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`FROM `QSOptimize_province`WHERE `QSOptimize_province`.`id` = 2 ; SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`FROM `QSOptimize_province`WHERE `QSOptimize_province`.`id` = 1 ;

注:这里的SQL语句是直接从Django的logger:‘django.db.backends'输出出来的

如果我们使用select_related()函数:
 

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

就只有一次SQL查询,显然大大减少了SQL查询的次数:
 

SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`,`QSOptimize_city`.`province_id`, `QSOptimize_province`.`id`, `QSOptimize_province`.`name`FROM`QSOptimize_city`INNER JOIN `QSOptimize_province` ON (`QSOptimize_city`.`province_id` = `QSOptimize_province`.`id`) ;            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表