Model性能相关操作:select_related

1.普通查询的缺点

1.例:现在有两张表user和show两张表,在user表中使用m作为ForeignKey与show表进行一对多关联
2.如果通过user表中的实例查找对应的show表中的数据,就必须重复发送sql请求
3.prefetch_related()和select_related()的设计目的,都是为了减少SQL查询的数量,但是实现的方式不一样

2.select_related作用

1.select_related主要针对一对一和多对一关系进行优化。
2.select_related使用SQL的JOIN的语句进行优化,通过减少SQL查询的次数进行优化、提高性能。

3.prefetch_related()作用

1.prefetch_related()主要对于多对多字段和一对多字段进行优化
2.进行两次SQL查询,将查询结果拼接成一张表放在内存中,再查询就不用发SQL请求

4.select_related与prefetch_related使用原则

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

5.select_related举例说明

作用:使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化
def index(request):
    #1 这种方法低效
    users = models.User.objects.all()    #拿到的仅仅是user表中内容
    for row in users:
        print(row.user,row.ut_id)        #这里打印user表中的内容不必再次sql请求
        print(row.ut.name)               #第一次查表,没有拿到关联表ut字段中的内容
                                         #所以每次循环都会再次发sql请求,拿到ut.name的值,低效

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

    #3 select_related()可以一次sql查询拿到所有关联表信息
    users = models.User.objects.all().select_related()
    
    # 这里还支持指定只拿到那个关联表的所有信息,比如:有多个外键关联,只拿到与ut外键关联的表
    users = models.User.objects.all().select_related('ut')


# select_related() 接受depth参数,depth参数可以确定select_related的深度。
# Django会递归遍历指定深度内的所有的OneToOneField和ForeignKey。以本例说明:
# zhangs = Person.objects.select_related(depth = d)
# d=1  相当于 select_related(‘hometown’,'living’)
# d=2  相当于 select_related(‘hometown__province’,'living__province’)

6、prefetch_related举例说明
作用:进行两次sql查询,将查询结果拼接成一张表

def index(request):
    users = models.User.objects.filter(id__gt=30).prefetch_related('ut')
                       #ut和tu是user表的两个foreign key,分别关联不同的表

    users = models.User.objects.filter(id__gt=30).prefetch_related('ut','tu')
    #1 先执行第一次sql查询:select * from users where id > 30;
    #2 比如:第一次查询结果,获取上一步骤中所有ut_id=[1,2]
    #3 然后执行第二次sql查询:select * from user_type where id in [1,2]
    #4 这样就仅执行了两次sql查询将两个表的数据拼到一起,放到内存中,再查询就不用发sql请求
    for row in users:
        print(row.user,row.ut_id)       #这里打印user表中的内容不必再次sql请求

你可能感兴趣的:(Model,python)