Django之ORM查询优化

res = models.Book.objects.all()
    # 如果此时直接运行,不调用这个结果,终端将什么也不会打印出来
    # 原因:惰性查询,减少不必要的数据库操作,降低数据库的压力

only 和 defer

only 的优化机制:

res = models.Book.objects.only('title')		# 括号内查询的字段可以有多个
print(res)        # 查询一次,打印一条sql查询语句
for i in res:
    print(i.title)  # 查询一次,打印一条sql查询语句
    print(i.price)  # 有几个对象,就查询几次,打印几条sql查询语句

defe 的优化机制:

res = models.Book.objects.defer('title')	# 括号内查询的字段可以有多个
print(res)              # 查询一次,打印一条sql查询语句
for i in res:
    print(i.title)      # # 有几个对象,就查询几次,打印几条sql查询语句
    print(i.price)        # 查询一次,打印一条sql查询语句

only 与 defer 的区别:

共同点:两者括号内都可以放数据库字段,查询结果都是一个列表套一个个的数据对象。

不同点:

  • only:数据对象里面封装了括号内查询的字段,直接点这个括号内字段属性不需要再次查询数据库

    ​ 如果查询括号内没有的字段,每查询一次,就需要去数据库中重新查询,效率低

  • defer:数据库中封装了相当于除括号内查询的字段,直接点这个括号内字段属性需要再次查询数据库,如果查询括号内没有的字段,就不需要再次查询数据库,效率高

select_related 和 prefetch_related

select_related :

res = models.Book.objects.select_related('publish')	# 支持放多个外键字段
print(res)      # 查询外键字段,连表查询
for i in res:
    print(i.publish.name)   # 连表查询一次,一条sql语句
    print(i.title)          # 连表查询一次,一条sql语句

prefetch_related:

res = models.Book.objects.prefetch_related('publish')	# 支持放多个外键字段
print(res)  # 查询外键字段,子查询
for i in res:
    print(i.publish.name)  # 子查询查询一次,一条sql语句
    print(i.title)  # 子查询查询一次,一条sql语句

select_related 和 prefetch_related 的区别:

共同点:括号内只能放外键字段,并且外键字段关系只能是一对多、一对一,不能是多不多

不同点:

  • select_related:内部是连表(left/right join)查询,查询的时候不需要再次查询数据库
  • prefetc_related:内部是子查询,查询多张表,将查询结果封装到对象中,如果括号内外键字段比较多,则查询次数较多。

结合实际情况,哪种查询更加好?

select_related 查询需要连表,数据量大可能耗时比较久

prefetc_related 查询多张表,数据量大可能查询次数多一点,但是时间较快

ORM字段参数 choices

字段参数choices可以按照提前设计好的对应关系,存取对应真正的数据

models.py:
class User(models.Model):
    user = models.CharField(max_length=64)
    pwd = models.IntegerField()
    gender_choices = (
        (1,'男'),
        (2,'女')
    )
    gender = models.IntegerField(choices=gender_choices)
    

手动插入数据:
id	user	pwd	gender
1	qinyj	123	1
2	jack	123	2
from app01 import models
user_obj = models.User.objects.get(pk=1)
print(user_obj.get_gender_display())

只要是choices字段类型,在获取值的时候需要这样写:get_字段名_display()

posted @ 2019-11-29 22:46  GeminiMp  阅读(248)  评论(0编辑  收藏  举报