Django中的select_related与prefetch_related

Django是一个基于Python的网站开发框架,一个很重要的特点就是Battery Included,简单来说就是包含了常规开发中所需要的一切东西,包括但不限于完整的ORM模型、中间件、会话处理、模板语言、路由映射、管理员站点等,大大提高了开发者的开发体验,今天要谈的东西便是属于Django ORM这块中查询集优化的内容。

在实际的开发中,模型之间经常存在复杂的关联关系。在数据量较大的情况下,默认的查询可能面临潜在的性能问题。今天我们就分享一下Django ORM的查询优化。

首先需要明确一点:

Queryset是惰性求值的。

在Django中,所有的Queryset都是惰性的,意思是当创建一个查询集的时候,并没有跟数据库发生任何交互。因此我们可以对查询集进行级联的filter等操作,只有在访问Queryset的内容的时候,Django才会真正进行数据库的访问。而多频率、复杂的数据库查询往往是性能问题最大的根源。

为了方便说明,我们定义以下model:

1 class A(models.Model):
2     foo = models.IntegerFiled()
3 
4 class B(models.Model):
5     a = models.ForeignKey(A, related_name='bs')

 

关联关系中,外键的查询依然是惰性的。当我们通过外键获取一个关联对象的时候,实际上默认获取的是关联对象的ID。这种情况适用于只需要ID而不需要实际的关联对象的场景,这点在Django的文档中有相关说明:

If you only need a foreign key value, use the foreign key value that is already on the object you’ve got, rather than getting the whole related object and taking its primary key.

不过我们实际开发中,往往需要访问到外键对象的其他属性。如果按照默认的查询方式去遍历取值,那么会造成多次的数据库查询,效率可想而知。

select_related和prefetch_related正是为了解决这个问题,他们可以达到这样的目的:在查询对象集合的时候,把指定的外键对象也一并完整查询加载,避免后续的重复查询。

因此,我们可以通过下面的方式来获取B的外键关系对象A的信息:

1 b = B.objects.select_related('a').all()
2 
3 for temp_b in b:
4     print temp_b.a.foo

以上方式,实际上只会触发一次数据库查询,会极大的提升查询性能。

prefetch_related效果和select_related类似,不过使用的场景不同:

1,select_related适用于外键和多对一的关系查询;

2,prefetch_related适用于一对多或者多对多的查询。

 
 

转载于:https://www.cnblogs.com/yonguo123/p/9712963.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值