Django实例讲解:用prefect_related解决join操作导致数据膨胀的问题
Admin 2023-01-06 群英技术资讯 1108 次浏览
今天小编跟大家讲解下有关“Django实例讲解:用prefect_related解决join操作导致数据膨胀的问题”的内容 ,相信小伙伴们对这个话题应该有所关注吧,小编也收集到了相关资料,希望小伙伴们看了有所帮助。django-debug-toolbar的安装
select_related:
将会根据外键关系(注意: 仅限单对单和单对多关系),在执行查询语句的时候通过创建一条包含SQL inner join操作的SELECT语句来一次性获得主对象及相关对象的信息
prefetch_related
对于多对多字段,你不能使用select_related方法,这样做是为了避免对多对多字段执行JOIN操作从而造成最后的表非常大。
Django提供了prefect_related方法来解决这个问题。
prefect_related可用于多对多关系字段,也可用于反向外键关系(related_name)。
相同点:
都作用于queryset对象上面
注意点:
- 对与单对单或单对多外键ForeignKey字段,使用select_related方法
- 对于多对多字段和反向外键关系,使用prefetch_related方法
- 两种方法均支持双下划线指定需要查询的关联对象的字段名
- 使用Prefetch方法可以给prefetch_related方法额外添加额外条件和属性。
表
from django.db import models
class UserInfo(models.Model):
username = models.CharField(verbose_name='用户名', max_length=225)
def __str__(self):
return self.username
class Tag(models.Model):
name = models.CharField(verbose_name='标签名称', max_length=225)
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(verbose_name='标题', max_length=225)
content = models.CharField(verbose_name='内容', max_length=225)
# 外键
username = models.ForeignKey(verbose_name='用户', to='UserInfo', on_delete=models.DO_NOTHING)
tag = models.ManyToManyField(verbose_name='标签', to='Tag')
def __str__(self):
return self.title
def article_list(request):
if request.method == 'GET':
# select_related---->queryset
article_queryset = models.Article.objects.all()
return render(request, 't2.html', context={'article_queryset': article_queryset})

1.从图示我们可以看出来,一共进行13次查询,且有10次重复的!!!
原因是:当我们第一次查询时,返回的值,只有文章对象,对于标签以及用户,并没有查询,当前端界面需要这两个时,每循环一次,就会去数据库查询一次
2.为了避免重复查询,django提供select_related和prefetch_related方法来提升数据库查询效率,类似于SQL的JOIN方法。
3.效果就是当第一次查询时,进行连表,一次性把所有数据全部查询到
from django.shortcuts import render
from blog import models
def article_list(request):
if request.method == 'GET':
# select_related---->queryset
article_queryset = models.Article.objects.all().select_related('tag', 'username')
return render(request, 't2.html', context={'article_queryset': article_queryset})

可以看到现在只有三次查询,耗时大大减少
# 获取id=1的文章对象同时,获取其相关username信息
Article.objects.select_related('username').get(id=1)
# 获取id=1的文章对象同时,获取其相关作者名字信息
Article.objects.select_related('username__username').get(id=1)
# 获取id=1的文章对象同时,获取其相关tag和相关作者名字信息。下面方法等同。
# 方式一:
Article.objects.select_related('tag', 'username__username').get(id=1)
# 方式二:
Article.objects.select_related('tag').select_related('username__username').get(id=1)
# 使用select_related()可返回所有相关主键信息。all()非必需。
Article.objects.all().select_related()
# 获取Article信息同时获取username信息。filter方法和selected_related方法顺序不重要。
# 方式一:
Article.objects.filter(tag__gt=3).select_related('username')
# 方式二:
Article.objects.select_related('username').filter(tag__gt=3)
对于多对多字段,你不能使用select_related方法,这样做是为了避免对多对多字段执行JOIN操作从而造成最后的表非常大。
articles = Article.objects.all().select_related('category').prefecth_related('tags')
# 文章列表及每篇文章的tags对象名字信息
Article.objects.all().prefetch_related('tags__name')
# 获取id=13的文章对象同时,获取其相关tags信息
Article.objects.prefetch_related('tags').get(id=13)
# 获取文章列表及每篇文章相关的名字以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'
)
本文参考
Django基础(29): select_related和prefetch_related的用法与区别
https://www.jb51.net/article/266493.htm
https://www.jb51.net/article/266498.htm
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
由于公司设置网络代理,mnist.load_data()失败,原因是公司的网络代理未设置导致。
这篇文章主要介绍了python 实现添加标签&打标签的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
这篇文章主要介绍了Python登录系统界面实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,,需要的朋友可以参考下
python中map函数和filter函数有什么区别?map函数根据给定函数对指定序列做映射;
本文结合实例,详细的介绍了泛洪填充算法的具体使用,具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008