QuerySet

 

QuerySet是惰性的——创建QuerySet的行为不涉及任何数据库活动。
只有在拿结果的时候才会连接数据库
a = TB.objects.all()
b = a.filter(id=1)
print(b)
只有在执行 print(b) 的时候才会连接数据库

select_related

返回一个QuerySet,当执行它的查询时,它沿着外键关系查询关联的对象的数据。它会生成一个复杂的查询并引起性能的损耗,但是在以后使用外键关系时将不需要数据库查询。

对于一对一字段(OneToOneField)和外键字段(ForeignKey),可以使用select_related 来对QuerySet进行优化,在对QuerySet使用select_related()函数后,Django会获取相应外键对应的对象,从而在之后需要的时候不必再查询数据库了。
 
 
# 连接数据库
e = Entry.objects.get(id=5)

# 再次连接数据库以获取相关的Blog对象
b = e.blog
# 连接数据库
e = Entry.objects.select_related('blog').get(id=5)

# 没有进入数据库,因为e.blog已经预填充在前面的查询中。
b = e.blog

  

  • select_related主要针一对一和多对一关系进行优化。
  • select_related使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。
  • 可以通过可变长参数指定需要select_related的字段名。也可以通过使用双下划线“__”连接字段名来实现指定的递归查询。没有指定的字段不会缓存,没有指定的深度不会缓存,如果要访问的话Django会再次进行SQL查询。
  • 也可以通过depth参数指定递归的深度,Django会自动缓存指定深度内所有的字段。如果要访问指定深度外的字段,Django会再次进行SQL查询。
  • 也接受无参数的调用,Django会尽可能深的递归查询所有的字段。但注意有Django递归的限制和性能的浪费。


prefetch_related

这允许它预取多对多和多对一对象,因为它们不能使用select_related来完成。

select_related主要是执行跨表操作,而prefetch_related不是跨表操作,而是对每个表分别执行SQL查询(Django内部在您使用时自动会帮你像跨表操作一样连接起来),从而减少跨表查询,提升性能。

小结

  1. 因为select_related()总是在单次SQL查询中解决问题,而prefetch_related()会对每个相关表进行SQL查询,因此select_related()的效率通常比后者高。
  2. 鉴于第一条,尽可能的用select_related()解决问题。只有在select_related()不能解决问题的时候再去想prefetch_related()
  3. 你可以在一个QuerySet中同时使用select_related()prefetch_related(),从而减少SQL查询的次数。
  4. 只有prefetch_related()之前的select_related()是有效的,之后的将会被无视掉。
 
 
 
 
 
 
 



posted on 2019-05-27 11:23  webch  阅读(161)  评论(0)    收藏  举报

导航