如何理解Django查詢集的緩存特性
查詢集概念
查詢集,也稱查詢結果集、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: