1. QuerySet是惰性的
articles = Article.objects.filter(content__contains="python")
但是当我们定义articles的时候,Django的数据接口QuerySet并没有对数据库进行查询。只有当你需要对articlest做进一步运算时,Django才会真正执行对数据库的查询。
for article in articles:
print(article.content)
2. QuerySet自带缓存
当你遍历queryset时,所有匹配的记录会从数据库获取。这些结果会载入内存并保存在queryset内置的cache中。这样如果你再次遍历或读取该queryset时,Django就不需要重复查询了,这样也可以减少对数据库的查询。
如果我们只希望知道查询结果是否存在,而不需要使用查询结果。这时可以用exists()方法。与if判断不同,exists只会检查查询结果是否存在,返回True或False,而不会缓存articles。
if articles.exists():
print("存在!")
else:
print("不存在")
注意: 判断查询结果是否存在到底用if还是exists取决于你是否希望缓存查询数据集复用,如果是用if,反之用exists。
3. 统计查询结果数量count方法较快
len()与count()均能统计查询结果的数量。一般来说count更快,因为它是从数据库层面直接获取查询结果的数量,而不是返回整个数据集,而len会导致queryset的执行,需要将整个queryset载入内存后才能统计其长度。
但是:如果数据集queryset已经在缓存里了,使用len更快,因为它不需要跟数据库再次打交道。
num = Article.objects.filter(content__contains="python").count()
4. 当queryset非常大时,我们可以只提取部分值
articles = Article.objects.filter(content__contains="python").values('content')
if articles:
print(article.content)
articles = Article.objects.filter(content__contains="python").values_list('id', 'content')
if articles:
print(article.content)
注意: 早起版本values和values_list返回的是字典形式字符串数据,而不是对象集合,
新版本:values可以输入多个参数,返回的也是queryset查询集,而values_list不支持了
5. 更新数据库部分字段update方法高效
save()方法需要把整个Article对象的数据先提取出来,缓存到内存中,变更信息后再写入数据库。update()方法直接对标题做了更新,不需要把整个文章对象的数据载入内存,显然更高效
article = Article.objects.get(id=1)
Article.title = "python"
article.save()
Article.objects.filter(id=1).update(title='python')
6. explain方法的使用
可以统计一个查询所消耗的执行时间。这可以帮助我们更好地优化查询结果。
print(Article.objects.filter(title='python').explain(verbose=True))