Django对象关系映射模式(ORM)中查询集(QuerySet)的缓存特性
查询集概念
查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。
当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表):
- all(): 返回所有数据
- filter(): 返回满足条件的数据
- exclude(): 返回满足条件之外的数据
- order_by(): 对结果进行排序
对查询集可以再次调用过滤器进行过滤,如:
BookInfo.objects.filter(bread__gt=30).order_by('bpup_date')
判断某一个查询集中是否有数据:
exists(): 判断查询集中是否有数据,如果有则返回True,没有则返回False
查询集的两大特性——惰性执行、缓存
一、惰性执行
创建查询集不会访问数据库,直到调用数据时才会访问数据库,调用数据的情况包括迭代、序列化、与if合用等。
例如,当执行如下语句时,并未进行数据库查询,只是创建了一个查询集qs:
qs = BookInfo.objects.all()
继续执行遍历迭代操作后,才能真正进行数据库的查询:
>>> for book in qs:
>>> print(book.btitle)
二、缓存
每个QuerySet都带有缓存,可以尽量减少数据库的访问次数。对新创建的查询集执行遍历迭代操作时,会触发查询集的缓存特性,Django会将整个查询集完整缓存下来,后续对同一个QuerySet的查询会复用缓存结果。
>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset]) # Evaluate the query set.
>>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.
两个不同的查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载:
>>> from booktest.models import BookInfo
>>> [book.id for book in BookInfo.objects.all()]
>>> [book.id for book in BookInfo.objects.all()]
查询结果集并不总是缓存结果。当仅计算查询结果集的部分时,会校验缓存,若没有填充缓存,则后续查询返回的项目不会被缓存。特别地说,这意味着使用数组切片或索引的限制查询结果集不会填充缓存。
例如,重复的从某个查询结果集对象中取指定索引的对象会每次都查询数据库:
>>> queryset = Entry.objects.all()
>>> print(queryset[5]) # Queries the database
>>> print(queryset[5]) # Queries the database again
不过,若全部查询结果集已被检出,就会去检查缓存:
>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database
>>> print(queryset[5]) # Uses cache
>>> print(queryset[5]) # Uses cache
以下动作会触发查询集的缓存特性:
>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)
>>> if queryset: