select_related & prefetch_related

# models

class User(models.Model):
    username = models.CharField(max_length=32)
    pwd = models.CharField(max_length=64)

    # 反向操作时,使用的连接前缀,用于替换 表名
    # 如:models.UserGroup.objects.filter(a__字段名=1).values('a__字段名')
    ut = models.ForeignKey(to=UserTypes,to_field='id',related_query_name='a',on_delete=models.CASCADE)


class UserTypes(models.Model):
    user_type_name = models.CharField(max_length=32)

    def __str__(self):
        return self.user_type_name          #只有加上这个,django amdin才显示表名
# views

from django.http import HttpResponse
from django.shortcuts import render
from app import models
# Create your views here.


"""
普通查询的缺点:
  1. 例如:现在有俩张表 User , 和 UserTypes 这俩张表,在User 表中使用s作为Foreignkey与UserTypes进行以对多关联
  2. 如果通过User表中的实例查找对应的UserTypes表的数据,就必须发送重复的sql语句
  3. prefetch_related() 和 select_related()的设计目的,都是为了减少sql查询的数量,但是实现方式不一样
  
  
select_related 作用
    1. select_related 主要针对 一对一和多对一关系进行优化
    2. select_related 使用SQL的json语句进行优化,通过减少SQL查询的次数来进行优化,提高性能
    
prefetch_related 作用
    1. prefetch_related 主要对于多对多字段和一对多字段进行优化
    2. 进行俩次sql查询,将查询结果拼接成一张表存在内存中,在查询就不用发sql请求

select_related 与prefetch_related 使用原则
    1. prefetch_related 和 select_related的设计目的很相似,都是为了减少sql查询的数量,但是实现方式不一样
    2. 因为select_related 总是在单次sql查询中解决问题,而prefetch_related 会对每个相关表进行sql查询,因此select_related的效率高
    3. 所以尽可能的用select_related 解决问题,只有在select_related 不能解决问题的时候在去想prefetch_related
    
"""

def index(request):
    if request.method == 'GET':
        # users = models.User.objects.all()   # 仅仅拿到user表中的内容
        # for row in  users:
        #     print(row.username,row.id)      # 这里打印user表中的内容不必再次sql请求
        #     print(row.ut.user_type_name)    # 第一次查表,没有拿到关联的ut字段的内容  # 所以每次循环再次发sql请求



        # 使用这样的方法也仅需要一次数据库查询(拿到的是字典) 但是如果查找的不在那些字段中直接报错
        # users = models.User.objects.all().values('username','pwd','ut__user_type_name')

        # select_related  可以一次sql查询拿到所有关联表信息
        # users = models.User.objects.all().select_related()
        # print(users)


        # 这里还支持指定只拿到那个关联表所有信息,比如:有多个外键,只能拿到ut外键关联表
        # users = models.User.objects.all().select_related('ut')
        # print(users)
        pass
    return HttpResponse('ok')


def indexs(request):
    if request.method  == 'GET':
        # users = models.User.objects.filter(id__gt=1).prefetch_related('ut')
        # ut 和 tu 是 user 表中的俩个Foreign Key 分别关联不同的表
        users = models.User.objects.filter(id__gt=1).prefetch_related('ut','tu')
        # 先执行第一次sql查询:select * from users where id > 1
        # 比如:第一次查询结果,获取上一步骤中所有的id
        # 然后执行第二次sql查询:select * from  user where id in [1,2]
        # 这样就仅执行了俩次sql查询将俩个表的数据拼接到一起,放到内存中,在查数据就不要sql请求
        for row in users:
            print(row.user,row.ut_id)
        # print(users)
    return HttpResponse('ok')

 

posted @ 2020-07-10 10:05  Handsome、Snake  阅读(215)  评论(0编辑  收藏  举报