QuerySet的特性:惰性和缓存等
对QuerySet的理解
是什么?(what)
QuerySet是Django的Model中的一种非常重要的概念, 在编写django项目时, 我们会经常用到这一概念. 因为后端的代码与数据库的所有交互都是通过它来完成的.
Model.objects.all() # 最常见的queryset
- 1
为什么要用?(why)
QuerySet 可以被构造,过滤,切片,做为参数传递,这些行为都不会对数据库进行操作. 在使用queryset获取数据库中的数据之前, 实际上没有发送任何数据库活动.
也就是说, 合理地利用queryset可以大大减少数据库的交互次数, 从而使程序能够以更高的效率执行
怎么用?(how)
QuerySet具有以下特性:
- 可切片
- 可迭代
- 惰性
- 缓存
可切片
可以使用python的切片语法来限制queryset记录的数目, 其作用等价于SQL的LIMIT
和OFFSET
子句。
>>> User.objects.all()[:5] # (LIMIT 5)
>>> User.objects.all()[5:10] # (OFFSET 5 LIMIT 5)
- 1
- 2
可迭代
QuerySet是可迭代类型,
>>> usersList=User.objects.all()
>>> for user in usersList:
print(user.name)
- 1
- 2
- 3
- 4
当您第一次对其进行迭代时,它将执行其数据库查询. 若之后还有语句访问相同的内容, 这可以直接加载, 不用再访问数据库, 这是其另一特性: 缓存
惰性
就像前面所说的query在被构造,切片等操作时不会对数据库操作, 这里就是queryset惰性, 也叫惰性查询
也就是说单纯的创建queryset
那么, 什么操作会使queryset进行数据库活动呢? 官方文档给出了我们很多例子:
- 迭代(Iteration),
for i in queryset
- 切片(Slicing), 带有步长的切片,
queryset[::2]
- 索引,
queryset[0]
- 序列化/缓存化(Pickling/Caching), 将数据保存到redis中或者内存中的时候
- repr(). 直接打印,
print(queryset)
- len().
len(queryset)
- list().
list(queryset)
- bool().
queryset if queryset else None
缓存
序列化缓存, 就是先将查询对象载入到内存中以完成序列化,这样你之后就可以第一时间使用对象(直接从数据库中读取数据需要一定时间,这正是缓存所想避免的)。
**序列化(Pickling)是缓存化(Caching)**的先行工作,所以在缓存查询时,首先就会进行序列化工作。
这意味着当你反序列化 QuerySet 时,第一时间就会从内存中获得查询的结果,而不是从数据库中查找。
如何实现缓存? 先来来看一段代码:
>>> queryset = Model.objects.all()
>>> print(queryset[1]) # 访问了数据库
>>> print(queryset[1]) # 再次访问了数据库
- 1
- 2
- 3
在这段代码中, 对queryset进行两次索引取值, 每一次取值查询, 都会访问数据库
但如果一次性将queryset中的全部值查询出来,若再次取值则将检查缓存
>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # 访问了数据库
>>> print(queryset[1]) # 访问缓存
>>> print(queryset[1]) # 访问缓存
- 1
- 2
- 3
- 4
这就是最简单的缓存化方式
下面是一些其它例子,和上面的for循环相同的一点是, 它们会查询queryset中全部的值并填充到缓存中:
>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)
- 1
- 2
- 3
- 4
参考文章链接:QuerySet
更多内容请移步至官方文档:When QuerySets are evaluated
</div>
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-095d4a0b23.css" rel="stylesheet">
</div>
</article>
<div class="postTime">
<p class="article-bar-bottom"></p>
<span>
文章最后发布于: 2019年08月19日 23:04:06 </span>
</div>