前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >django select_related和prefetch_related的用法与区别

django select_related和prefetch_related的用法与区别

作者头像
kirin
发布于 2021-05-08 06:43:24
发布于 2021-05-08 06:43:24
1.5K0
举报
文章被收录于专栏:Kirin博客Kirin博客

在前面教程中小编我已经介绍了Django的Queryset特性及高级使用技巧以及Queryset的aggregate和annotate方法。这些技巧和方法都是为了减少对数据库的访问次数和对内存的占用,从而提升网站性能。今天我们再来学习两个非常重要的查询方法select_related和prefetch_related方法,看看如何使用它们避免不必要的数据库查询。高手过招,只差分毫。专业和业余之前的区别就在细节的处理上。为了让大家更直观地看到这两个方法的作用,我们将安装使用django-debug-toolbar这个流行的Django第三方包。

django-debug-toolbar的安装

第一步:pip install django-debug-toolbar

第二步:打开项目文件夹settings.py 文件, 把”debug_toolbar”加到INSTALLED_APP里去。

第三步: 打开项目文件夹里的urls.py, 把debug_toolbar的urls加进去。

from django.conf import settings from django.conf.urls import include, url # For django versions before 2.0 from django.urls import include, path # For django versions from 2.0 and up

if settings.DEBUG: import debug_toolbar urlpatterns = [ path(‘__debug__/’, include(debug_toolbar.urls)),

] + urlpatterns 第四步:  在settings.py里添加中间件

MIDDLEWARE = [ # … ‘debug_toolbar.middleware.DebugToolbarMiddleware’, # … ] 第五步: 在settings.py设置本地IP, debug_toolbar只能在localhost本地测试环境下运行。 INTERNAL_IPS = [ # … ‘127.0.0.1’, # … ] 当你安装好debug_toolbar后,启动django服务器,打开任何一个页面你都可以看到查询数据库所花时间以及是否有相似及重复的查询,如下图所示:

言归正传

假设我们有如下一个文章(Article)模型,其与类别(Category)是单对多地关系(ForeignKey), 与标签(Tag)是多对多的关系(ManyToMany)。我们需要编写一个article_list的函数视图,以列表形式显示文章清单及每篇文章的类别和标签,我们常规做法如下:

#models.py

class Article(models.Model): “””文章模型””” title = models.CharField(‘标题’, max_length=200, db_index=True) category = models.ForeignKey(‘Category’, verbose_name=’分类’,

on_delete=models.CASCADE, blank=False, null=False)

tags = models.ManyToManyField(‘Tag’, verbose_name=’标签集合’, blank=True) #views.py

def article_list(request): articles = Article.objects.all() return render(request, ‘blog/article_list.html’, {‘articles’: articles, }) 我们的模板代码会如下所示:

#blog/article_list.html

<ul> {% for article in articles %} <li>{{ article.title }} </li> <li>{{ article.category.name }}</li> <li> {% for tag in article.tags.all %} {{ tag.name }}, {% endfor %} </li> {% endfor %} </ul> 上面代码运行是没有错的,只是效率很低。使用debug_toolbar可以让我们更深入地看问题。它提示我们查询了10次数据库,包括3次重复查询,一共耗时8.93ms。

什么?显示一个页面竟用了10次查询?是的,你没看错。我们先分析下这会什么会发生,然后再解释如何使用select_related和prefetch_related方法解决这个问题。

为什么会有重复查询?

当我们使用Article.objects.all()查询文章时,我们做了第一次数据库查询,查询的是blog_article数据表, 得到的数据只是文章对象列表,然而并没有包含与每篇文章相关联的category和tags对象信息。当我们在模板中调用{{ article.category.name }} 和 {{ tag.name }}显示category和tags的名字时,Django还需要重新查询blog_category和blog_tag数据表获取名字。for循环每运行一次,django都要对数据库进行一次查询,造成了极大的资源浪费。为什么我们不能再第一次获取文章列表的同时就获取每篇文章相关联的category和tags对象信息呢?Django考虑到了这一点,所以提供select_related和prefetch_related方法来提升数据库查询效率,类似于SQL的JOIN方法。

select_related方法

select_related将会根据外键关系(注意: 仅限单对单和单对多关系),在执行查询语句的时候通过创建一条包含SQL inner join操作的SELECT语句来一次性获得主对象及相关对象的信息。现在我们对article_list视图函数稍微进行修改,加入select_related方法,在查询文章列表时同时一次性获取相关联的category对象信息,这样在模板中调用 {{ article.category.name }}时就不用再查询数据库了。

def article_list(request): articles = Article.objects.all().select_related(‘category’) return render(request, ‘blog/article_list.html’, {‘articles’: articles, }) 运行结果如下图所示,查询次数由10次变为了7次,时间降到了2.99ms。

selected_related常用使用案例如下:

# 获取id=13的文章对象同时,获取其相关category信息 Article.objects.select_related(‘category’).get(id=13)

# 获取id=13的文章对象同时,获取其相关作者名字信息 Article.objects.select_related(‘author__name’).get(id=13)

# 获取id=13的文章对象同时,获取其相关category和相关作者名字信息。下面方法等同。 Article.objects.select_related(‘category’, ‘author__name’).get(id=13) Article.objects.select_related(‘category’).select_related(‘author__name’).get(id=13)

# 使用select_related()可返回所有相关主键信息。all()非必需。 Article.objects.all().select_related()

# 获取Article信息同时获取blog信息。filter方法和selected_related方法顺序不重要。 Article.objects.filter(pub_date__gt=timezone.now()).select_related(‘blog’) Article.objects.select_related(‘blog’).filter(pub_date__gt=timezone.now())

prefetch_related方法

对于多对多字段,你不能使用select_related方法,这样做是为了避免对多对多字段执行JOIN操作从而造成最后的表非常大。Django提供了prefect_related方法来解决这个问题。prefect_related可用于多对多关系字段,也可用于反向外键关系(related_name)。我们对之前的article_list视图函数再做进一步修改,在查询文章列表的同时返回相关tags信息。

def article_list(request): articles = Article.objects.all().select_related(‘category’).prefecth_related(‘tags’) return render(request, ‘blog/article_list.html’, {‘articles’: articles, }) 运行结果如下。查询次数减少到5次,运行时间1ms,是不是很帅?

prefetch_related使用方法如下:

# 文章列表及每篇文章的tags对象名字信息 Article.objects.all().prefetch_related(‘tags__name’)

# 获取id=13的文章对象同时,获取其相关tags信息 Article.objects.prefetch_related(‘tags’).get(id=13) 现在问题来了,如果我们获取tags对象时只希望获取以字母P开头的tag对象怎么办呢?我们可以使用Prefetch方法给prefect_related方法添加条件和属性。

# 获取文章列表及每篇文章相关的名字以P开头的tags对象信息 Article.objects.all().prefetch_related( Prefetch(‘tags’, queryset=Tag.objects.filter(name__startswith=”P”)) )

# 文章列表及每篇文章的名字以P开头的tags对象信息, 放在article_p_tag列表 Article.objects.all().prefetch_related( Prefetch(‘tags’, queryset=Tag.objects.filter(name__startswith=”P”)), to_attr=’article_p_tag’ ) 小结

当你查询单个主对象或主对象列表并需要在模板或其它地方中使用到每个对象的关联对象信息时,请一定记住使用select_related和prefetch_related一次性获取所有对象信息,从而提升数据库查询效率,避免重复查询。如果不确定是否有重复查询,可使用django-debug-toolbar查看。

对与单对单或单对多外键ForeignKey字段,使用select_related方法

对于多对多字段和反向外键关系,使用prefetch_related方法

两种方法均支持双下划线指定需要查询的关联对象的字段名

使用Prefetch方法可以给prefetch_related方法额外添加额外条件和属性。 ———————————————— 版权声明:本文为CSDN博主「大江狗」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_42134789/article/details/100571539

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/05/04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
腾讯TMQ在线沙龙回顾|测试左移实践
测试左移实践 活动时间:2017年6月28日 QQ群视频交流 活动主题:TMQ在线沙龙第二十三期分享 本次分享的主题是:测试左移实践 共有214位测试小伙伴报名参加活动,在线观看视频人数 54人! 想知道活动分享了啥吗, 请往下看吧! 活动嘉宾 嘉宾简介 陈诚,腾讯手机管家专项测试工程师,目前主要负责手机管家的测试分析、接口测试、工具建设等。在安卓客户端、H5等领域有丰富的测试经验。 分享主题 1、测试左移的概念 2、测试左移方案:testng自动化方案和本地Mock方案 3、测试左移案例:手机管
腾讯移动品质中心TMQ
2018/02/08
8190
腾讯TMQ在线沙龙回顾|测试左移实践
腾讯TMQ在线沙龙回顾|线性回归&逻辑回归
线性回归&逻辑回归 活动时间:2017年12月27日QQ群视频分享 活动介绍:TMQ在线沙龙第三十七期分享 本次分享的主题:线性回归&逻辑回归。 共有73位测试小伙伴报名参加活动。 想知道活动分享了啥吗? 请往下看吧! 嘉宾 马蕾:腾讯地图专项测试工程师。目前主要负责地图导航业务效果评测,工具开发等。在各类效果评测和专项测试上有丰富的经验。 分享主题 1、线性回归和逻辑回归介绍 2、模型训练的一般过程和优化思路 3、测试工作中应用线性回归案例分享 4、测试工作中应用逻辑回归案例分享 问答环节 问:T
腾讯移动品质中心TMQ
2018/02/08
7130
腾讯TMQ在线沙龙回顾|线性回归&逻辑回归
推荐系统相关效果评测指标总结
一、背景 在互联网信息量爆炸式增长的今天,我们已然从信息匮乏时代走入信息过载的时代。在这样的时代背景下,用户在精准内容消费方面的需求也随之提高,由此浏览器作为移动流量的巨大入口,其角色也自然发生了变化——《艾媒:2017年上半年中国手机浏览器市场研究报告》中提到“目前中国手机浏览器已发展至内容聚合及服务平台阶段,成为移动互联网超级入口及内容聚合平台的手机浏览器产品能满足用户多样化功能需求和提供丰富多样的内容服务。”移动端浏览器的业务重心已经逐渐转向内容消费。而发展个性化推荐(无论内容来源为全局热点或者是个
腾讯移动品质中心TMQ
2018/12/25
9.4K0
推荐系统相关效果评测指标总结
【精品投稿】推荐系统评测心得
在介绍推荐算法评测之前,我先简单说下推荐系统,这里我以商品为例,简单描述下推流程,让大家更明白一些,一般推荐主要包含以下步骤: 召回->打分排序->透出
用户5521279
2019/06/02
1.3K0
腾讯TMQ在线沙龙|Code Review也有潜规则
Code Review也有潜规则 活动时间:2017年3月30日 QQ群视频交流 活动介绍:TMQ在线沙龙第十八期分享 本次分享的主题是:Code Review也有潜规则 共有114位测试小伙伴报名参加活动,在线观看视频人数 47人! 想知道活动分享了啥吗, 往下看吧! 活动嘉宾 嘉宾简介 张艳,腾讯高级测试工程师,在腾讯电脑管家测试团队负管家PC办公相关项目的测试工作,包括桌面搜索、跨度传输、健康小助手等项目的CR、功能、性能的测试工作,在CR方面有一定的实践经验。 分享主题 1、什么是Code
腾讯移动品质中心TMQ
2018/02/08
1.3K0
腾讯TMQ在线沙龙|Code Review也有潜规则
腾讯TMQ在线沙龙|APP推荐质量保障工作
报名啦!!! 零距离对话腾讯测试专家,获取更多测试经验。 TMQ沙龙活动第四十二期 特邀腾讯高级测试工程师——马国俊来给大家分享APP推荐质量保障工作。本次分享,会结合嘉宾的实践经验,从APP增量更新
腾讯移动品质中心TMQ
2018/06/08
1.7K0
腾讯TMQ在线沙龙|Android应用Dex分包之旅
Android应用Dex分包之旅 活动时间:2016年1月12日 QQ群视频交流 活动介绍:TMQ在线沙龙第十六期分享 本次分享的主题是Android应用Dex分包之旅。 共有42位测试小伙伴报名参加活动,在线观看视频人数18人~想知道活动分享了啥吗?往下看吧! 活动嘉宾 嘉宾简介 李金涛,腾讯高级测试工程师,负责过腾讯QQ浏览器专项测试及优化,目前主要负责腾讯应用宝专项测试及优化。有多年的后台开发和性能优化经验以及前端专项评测和优化经验。 分享主题 什么是Dex 为什么要分Dex Dex分包
腾讯移动品质中心TMQ
2018/02/08
1.1K0
腾讯TMQ在线沙龙|Android应用Dex分包之旅
腾讯TMQ在线沙龙|精准测试介绍
精准测试介绍 活动时间 : 2016年8月25日 QQ群视频交流 活动介绍 :TMQ在线沙龙第七期分享 本次分享的主题是介绍精准测试相关的知识。 共有123位测试小伙伴报名参加活动,在线观看视频人数55人~想知道活动分享了啥吗?往下看吧! 活动嘉宾 嘉宾简介 赵丽娜,腾讯高级测试工程师,负责腾讯地图开放平台和后台的测试工作。 有多年后台开发和项目管理经验,对SDK测试、接口测试和性能专项测试有一定了解。 分享主题 什么是精准测试 为什么要用精准测试 精准测试的理论基础 精准测试在行业中的现
腾讯移动品质中心TMQ
2018/02/06
2.1K0
腾讯TMQ在线沙龙|精准测试介绍
腾讯TMQ在线沙龙回顾|技术债
技术债 活动时间:2017年11月23日 QQ视频分享 活动介绍:TMQ在线沙龙第三十四期分享 本次分享的主题是:技术债 有72位测试小伙伴报名参加活动! 想知道活动分享了啥吗 请往下看吧! 嘉宾 2011年加入腾讯,现为大屏浏览器测试组副组长。曾在业务测试组以及专项测试组负责过性能测试,测试工具&平台开发以及负责手机游戏的测试工作。 分享主题 1、代码坏味道 2、理解技术债 3、技术债的天敌 问答环节 1、对于业务比较重的项目,业务流程变动频繁、开发周期短,如何去有效管理代码质量? 答:如果业务
腾讯移动品质中心TMQ
2018/02/08
9320
腾讯TMQ在线沙龙回顾|技术债
腾讯TMQ在线沙龙回顾|大数据
大数据 活动时间:2017年12月20日 斗鱼直播分享 活动介绍:TMQ在线沙龙第三十六期分享 本次分享的主题:大数据。 共有65位测试小伙伴报名参加活动。 想知道活动分享了啥吗? 请往下看吧! 嘉宾 刘楚蓉:腾讯高级测试工程师。过去主要负责移动端产品质量体系建设、自动化工具开发、大数据业务测试等。在移动端质量体系建设及大数据测试方面有丰富的经验。 分享主题 大数据业务介绍 研发效率提升思路 实例分享 问答环节 1、这个平台是使用的什么工具?自己开发的吗?和大数据有什么关系呢? 答:平台开发使用的是
腾讯移动品质中心TMQ
2018/02/08
1.1K0
腾讯TMQ在线沙龙回顾|大数据
腾讯TMQ在线沙龙回顾|后台测试案例分享
后台测试案例分享 活动时间:2017年9月28日 qq视频分享 活动介绍:TMQ在线沙龙第三十一期分享 本次分享的主题是:后台测试案例分享 共有66位测试小伙伴报名参加活动,在线观看视频人数 27人! 想知道活动分享了啥吗, 请往下看吧! 嘉宾 赵丽娜,腾讯专项测试工程师,有多年电信开发经验,目前负责腾讯地图基础业务包括后台服务、引擎及API级产品的质量保证工作。在底层服务开发和测试架构设计方面有比较丰富的经验。 分享主题 1、腾讯地图后台测试持续集成解决方案 2、腾讯地图后台测试体系 3、开发自测在
腾讯移动品质中心TMQ
2018/02/08
1.3K0
腾讯TMQ在线沙龙回顾|后台测试案例分享
万字长文带你了解推荐系统全貌!
如果说互联网的目标就是连接一切,那么推荐系统的作用就是建立更加有效率的连接,推荐系统可以更有效率的连接用户与内容和服务,节约了大量的时间和成本。
Datawhale
2020/10/27
7660
万字长文带你了解推荐系统全貌!
腾讯TMQ在线沙龙回顾|测试过程管理
测试过程管理 活动时间:2017年10月26日 qq视频分享 活动介绍:TMQ在线沙龙第三十二期分享 本次分享的主题是:测试过程管理 共有83位测试小伙伴报名参加活动,在线观看视频人数 36人! 想知道活动分享了啥吗, 请往下看吧! 嘉宾 程绪超,腾讯高级系统测试工程师。负责过小Q书桌、电脑管家的测试。目前主要负责电脑管家-游戏加速的系统测试工作。在测试建模和测试过程管理方面有丰富的经验。 分享主题 1、测试过程管理经常遇到的问题 2、如何培养整个团队的质量意识 3、如何根据需求类别制定通用测试策略
腾讯移动品质中心TMQ
2018/02/08
1K0
腾讯TMQ在线沙龙回顾|测试过程管理
腾讯TMQ在线沙龙回顾|电量测试
电量测试 活动时间:2017年9月19日 斗鱼直播分享 活动介绍:TMQ在线沙龙第三十期分享 本次分享的主题是:电量测试 在线平均人气 70人! 想知道活动分享了啥吗, 请往下看吧! 嘉宾 张媛,腾讯专项测试工程师,负责过社交类、安全类、浏览服务类产品专项测试。目前主要负责手机QQ浏览器自动化及性能相关测试。在移动客户端的性能测试及工具开发方面有丰富经验。 分享主题 1、业界通用的电量测试方法 2、我们需要的电量测试 3、电量测试自动化方案 4、经验总结 问答环节 1、PC端不通过usb的话,怎么发
腾讯移动品质中心TMQ
2018/02/08
2.3K0
腾讯TMQ在线沙龙回顾|电量测试
腾讯TMQ在线沙龙回顾|测试建模
测试建模 活动时间:2017年4月27日 QQ群视频交流 活动介绍: TMQ在线沙龙第二十期分享 本次分享的主题是:测试建模 共有72位测试小伙伴报名参加活动,在线观看视频人数 34人! 想知道活动分享了些啥吗, 请往下看吧! 活动嘉宾 嘉宾简介 黎懋靓,腾讯测试工程师,曾负责腾讯地图IOS和车载音乐的测试,目前主要负责,车载导航相关业务测试。在移动客户端测试方面有比较丰富的经验。 分享主题 1.测试建模是什么 2.为什么要测试建模 3.怎么开展测试建模 问答环节 1、ACC横坐标一般怎么定义?
腾讯移动品质中心TMQ
2018/02/08
8990
腾讯TMQ在线沙龙回顾|测试建模
聊一聊转行推荐的问题
每天给你送来NLP技术干货! ---- “搜推广”是企业里离钱最近的岗位,在CV/NLP越来越卷的当下,很多朋友起了转推荐算法的念头。我就经常收到此类私信和留言。今天这篇文章打算跟大家聊一聊转行推荐算法的问题。 从前途角度考虑,我是非常建议的。 1 大厂必备核心——推荐系统 从商业角度来讲,互联网主要起到平台作用,构建多方沟通桥梁,例如淘宝对应卖家和卖家,头条是信息产出方和读者,除了要满足用户本身的需求,还要考虑到商家的利益。 平台巩固流量,才能进一步的转化,达到盈利。这时候,推荐系统可能是一整个系统的核
zenRRan
2022/07/27
4000
聊一聊转行推荐的问题
达观数据:推荐系统评测标准制定经验分享
推荐系统是互联网发展至今最常见也重要的技术之一。如今各类APP、网站、小程序等所有提供内容的地方,背后都有推荐系统在发挥作用。
达观数据
2020/04/01
9410
推荐系统:石器与青铜时代
准确地说这个时代,不能称之为推荐系统的时代,这一个时代未能给每个用户构建属于他的推荐结果,没有很好地解决个性化长尾问题,所以这个可以叫前推荐时代。
石晓文
2019/07/24
5860
腾讯TMQ在线沙龙回顾|IOS测试利器—idb
IOS测试利器—idb 活动时间:2017年5月17日 QQ群视频交流 活动介绍:TMQ在线沙龙第二十一期分享 本次分享的主题是:IOS测试利器—idb 共有101位测试小伙伴报名参加活动,在线观看视频人数 27人! 想知道活动分享了啥吗, 请往下看吧! 活动嘉宾 嘉宾简介 樊林,腾讯专项测试工程师,负责过手机QQ、应用宝专项测试,目前主要负责应用宝创新项目测试以及启动速度专项优化。在移动客户端的测试方面以及相应工具开发方面有丰富的经验。 分享主题 1.idb是什么 2.为什么要做idb 3.id
腾讯移动品质中心TMQ
2018/02/08
1.7K0
腾讯TMQ在线沙龙回顾|IOS测试利器—idb
腾讯TMQ在线沙龙回顾|Android App质量监控及工具应用实战
活动介绍 TMQ第四十二期在线沙龙分享活动圆满结束啦! 本次分享的主题:Android App质量监控及工具应用实战 共有238位测试小伙伴报名参加活动。 想知道活动分享了啥吗? 请往下看吧! 嘉宾
腾讯移动品质中心TMQ
2018/06/08
2.9K0
推荐阅读
相关推荐
腾讯TMQ在线沙龙回顾|测试左移实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档