Loading

ORM性能相关

数据库

class Student(models.Model):
    name = models.CharField(max_length=32, verbose_name="姓名")
    classes = models.ForeignKey('Classes', on_delete=models.CASCADE)


class Classes(models.Model):
    name = models.CharField(max_length=32, verbose_name="班级")

当用对象跨表时,可见查询语句非常多

def index(request):
    students = models.Student.objects.all()
    for student in students:
        print(student.classes)
(0.000) SELECT "app01_student"."id", "app01_student"."name", "app01_student"."classes_id" FROM "app01_student"; args=()
(0.000) SELECT "app01_classes"."id", "app01_classes"."name" FROM "app01_classes" WHERE "app01_classes"."id" = 1; args=(1,)
(0.000) SELECT "app01_classes"."id", "app01_classes"."name" FROM "app01_classes" WHERE "app01_classes"."id" = 2; args=(2,)
(0.000) SELECT "app01_classes"."id", "app01_classes"."name" FROM "app01_classes" WHERE "app01_classes"."id" = 3; args=(3,)

values字段查询

def index(request):
    students = models.Student.objects.values('classes__name')
    for student in students:
        print(student)
SELECT "app01_classes"."name"
  FROM "app01_student"
 INNER JOIN "app01_classes"
    ON ("app01_student"."classes_id" = "app01_classes"."id")

做了连表查询,只是把结果存在了字典,不必须使用对象时,可采用values加 字段查询。

def index(request):
    students = models.Student.objects.all().select_related()#可加外键字段,实测作用一样
    for student in students:
        print(student.classes.name)
SELECT "app01_student"."id",
       "app01_student"."name",
       "app01_student"."classes_id",
       "app01_classes"."id",
       "app01_classes"."name"
  FROM "app01_student"
 INNER JOIN "app01_classes"
    ON ("app01_student"."classes_id" = "app01_classes"."id")

这样也是做了连表查询,而且返回的仍然是对象。

def index(request):
    students = models.Student.objects.all().prefetch_related('classes')#要加外键在字段
    for student in students:
        print(student.classes.name)
SELECT "app01_student"."id",
       "app01_student"."name",
       "app01_student"."classes_id"
  FROM "app01_student"
  
SELECT "app01_classes"."id",
       "app01_classes"."name"
  FROM "app01_classes"
 WHERE "app01_classes"."id" IN ('1', '2', '3')

可见做了子查询,返回结果也是对象。

only

def index(request):
    students = models.Student.objects.all().only('name')
    for student in students:
        print(student.name)
SELECT "app01_student"."id",
       "app01_student"."name"
  FROM "app01_student"

only只查某些 字段,与其相反的有个defer,不再举例。

小结

  1. 尽量不查对象,能用values()就用values

  2. select_related('classes') 连表查询 多对一 一对一

  3. prefetch_related('classes') 子查询 多对一 多对多

  4. only('name') 指定某些字段 defer 指定排除某些字段

posted @ 2019-09-08 17:25  陌路麒麟  阅读(70)  评论(0编辑  收藏  举报