Django学习之ORM性能相关
orm 性能相关
values
第一步:创建表
class Student(models.Model): name = models.CharField(max_length=32) classes = models.ForeignKey('Class',) class Class(models.Model): name = models.CharField(max_length=16)
views.py文件中
from django.shortcuts import render from app01 import models # Create your views here. def index(request): all_students = models.Student.objects.all().values('classes__id','classes__name') # all_students = models.Student.objects.all() for i in all_students: # print(i.name,i.classes_id) # 1.通过django-debug-toolbar可以看到 # 查询本表子段的时候用到了一次sql查询 # print(i.name,i.classes.id,i.classes.name) # 2.但是如果进行关联表数据的查询 print(i['classes__id'],i['classes__name']) # 4.首先通过values进行了连表操作,效率就高一些了 return render(request,'index.html',{'all_students':all_students})
select_related
但是如果查询结果,就想是对象,就想通过对象.属性的操作,怎么办呢?用到了select_related
from django.shortcuts import render from app01 import models # Create your views here. def index(request): all_students = models.Student.objects.all().select_related('classes') # 使用了select_related之后,里面的参数写的是关系字段的名称,那么就会先进行 # 连表操作,所以sql也是执行了一次,效率高一些,但是他用在外键或者一对一的关系上 for i in all_students: # print(i.name,i.classes_id) print(i.name,i.classes.id,i.classes.name)
prefetch_related
子查询效果。
from django.shortcuts import render from app01 import models # Create your views here. def index(request): all_students = models.Student.objects.all().prefetch_related('classes') # prefetch_related,里面的参数写的是关系字段的名称,那么会执行两次sql,子查询的效果,但是支持外键或一对一或者一对多的查询了 for i in all_students: # print(i.name,i.classes_id) print(i.name,i.classes.id,i.classes.name) return render(request,'index.html',{'all_students':all_students})
only和defer
当我们进行orm查询的时候,你通过翻译出来的sql语句可以看到,每次查询都是查询了每个字段的数据,所以我们通过only和defer,可以指定查询哪些字段数据
from django.shortcuts import render from app01 import models # Create your views here. def index(request): all_students = models.Student.objects.all().only('name')#只要这个字段数据 all_students = models.Student.objects.all().defer('name')#排除,除了这个字段其他字段数据都要 for i in all_students: print(i.name) return render(request,'index.html',{'all_students':all_students})
总结:
1.能用values的尽量不查询对象,然后对象.属性的操作 2.select_related 主动连表,针对一对一或者外键 3.perfetch_related 子查询 ,针对一对一或者外键或者多对多 4.only只查询指定字段数据 defer排除某些字段