一、惰性查詢python
二、緩存機制mysql
三、可迭代sql
四、可切片數據庫
-------------------------------------------------------
在一個新建立的查詢集中,緩存爲空。首次對查詢集進行求值 —— 同時發生數據庫查詢 ——Django
將保存查詢的結果到查詢集的緩存中並返回明確請求的結果(例如,若是正在迭代查詢集,則返回下一個結果)。
接下來對該查詢集 的求值將重用緩存的結果。
注意,當迭代完之後,第二次查詢,仍會操做數據庫
什麼時候查詢集不會被緩存?
1、重複獲取查詢集對象中一個特定的索引將每次都查詢數據庫 2、已經對所有查詢集求過值,則將檢查緩存 3、一些其它例子,它們會使得所有的查詢集被求值並填充到緩存中
queryset = Entry.objects.all() [entry for entry in queryset] # Queries the database print queryset[5] # Uses cache print queryset[5] # Uses cache
四、簡單地打印查詢集不會填充緩存。
exists: 只是簡單判斷queryset集是否有數據,但並不須要這些數據,用existsdjango
iterator:當數據量很是龐大時,一次性裝入內存是很是糟糕的,緩存
iterator()能夠一次只從數據庫獲取少許數據,這樣能夠節省內存, 迭代器協議ide
注意:雖然iterator能夠防止生成cache,但意味着遍歷同一個queryset時會重複執行查詢因此使 #用iterator()性能
的時候要小心,確保你的代碼在操做一個大的queryset時沒有重複執行查詢。fetch
就是多對多模型的第三張表,有時咱們不只須要有兩個foreign key,還要有一些其餘的信息,所以咱們須要添加一些其餘的字段。優化
那麼此時咱們就不能用add,set,create這些方法來給第三張表添加數據
此時那麼咱們就須要用
m1=Book2auth(person
=
paul, group
=
beatles,
date_joined
=
date(
1960
,
8
,
1
)
)
m1.save()
m2
=
Book2auth.objects.create(person
=
paul, group
=
beatles,
date_joined
=
date(
1960
,
8
,
1
)
)
這兩種方法來添加了
與性能有關 models.User.objects.all().only('id','name','age') # 只取 models.User.objects.all().defer('id','name','age') # 排除
only,defer 查出來的也是queryset類型,包含一個個obj
查出來的是queryset類型,其中包含一個個對象,但當獲取obj之外的字段外,會另外發起一次數據庫查詢
select_related用於一對一和外鍵查詢是對QuerySet進行了優化,會沿着外鍵關係查詢對象的數據,但會生成一個複雜的查詢並引發性能的損耗,但之後在使用外鍵關係時不須要數據庫查詢(join連表操做)
article=models.Article.objects.select_related("category").get(nid=1) print(article.articledetail) 兩次查詢
article=models.Article.objects.select_related("category","articledetail").
get(nid=1) print(article.articledetail) 查詢一次
article=models.Article.objects.select_related("blog").get(nid=1) print(article.blog.user.username) 依然要查詢兩次
由於第一次沒有查詢到userinfo表 article=models.Article.objects.select_related("blog__user").get(nid=1) print(article.blog.user.username) 一次
select_related主要針一對一和多對一關係進行優化。
select_related使用SQL的JOIN語句進行優化,經過減小SQL查詢的次數來進行優化、提升性能。
能夠經過可變長參數指定須要select_related的字段名。也能夠經過使用雙下劃線「__」鏈接字段名來實現指定的遞歸查詢。
沒有指定的字段不會緩存,沒有指定的深度不會緩存,若是要訪問的話Django會再次進行SQL查詢。
也能夠經過depth參數指定遞歸的深度,Django會自動緩存指定深度內全部的字段。若是要訪問指定深度外的字段,Django會再次進行SQL查詢。
也接受無參數的調用,Django會盡量深的遞歸查詢全部的字段。但注意有Django遞歸的限制和性能的浪費。
Django >= 1.7,鏈式調用的select_related至關於使用可變長參數。Django < 1.7,鏈式調用會致使前邊的select_related失效,只保留最後一個。
對於多對多字段(ManyToManyField)和一對多字段,可使用prefetch_related()來進行優化。
prefetch_related()和select_related()的設計目的很類似,都是爲了減小SQL查詢的數量,可是實現的方式不同。後者是經過JOIN語句,在SQL查詢內解決問題。可是對於多對多關係,使用SQL語句解決就顯得有些不太明智,由於JOIN獲得的表將會很長,會致使SQL語句運行時間的增長和內存佔用的增長。如有n個對象,每一個對象的多對多字段對應Mi條,就會生成Σ(n)Mi 行的結果表。
prefetch_related()的解決方法是,分別查詢每一個表,而後用Python處理他們之間的關係。
屢次單表操做,先查詢想要的數據,而後構造條件,如:id=[1,2,3],再次查詢其餘表根據id作條件
# 查詢全部文章關聯的全部標籤 article_obj=models.Article.objects.all() for i in article_obj: print(i.tags.all()) #4篇文章: hits database 5
改成prefetch_related:
# 查詢全部文章關聯的全部標籤 article_obj=models.Article.objects.prefetch_related("tags").all() for i in article_obj: print(i.tags.all()) #4篇文章: hits database 2
models.Book.objects.extra( select={"standard_time": "strftime('%%Y-%%m--%%d',create_time)'"},
# 能夠再select語句中添加其餘字段信息 select *** from *** as B select_params=(), where=['nid in (1,3) OR title like "%s"', 'nid>2'], # 各個條件之間爲且的關係 params=["py", ], # 與where對應 tables=None, order_by=["-nid", ], )
name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
# 若是SQL是其餘表時,必須將名字設置爲當前UserInfo對象的主鍵列名 models.Book.objects.raw("select id as nid from asd_userinfo",params=[],translations=name_map) # 對應關係
- 原生SQL from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() # fetchall()/fetchmany(..) PS: 選擇數據庫 queryset = models.Course.objects.using('default').all() # setting DATABASES 是一個字典,裏面默認只有default一個數據庫。
在獲取日期對象時截取年月 data_format(obj,"%Y-%m") # 針對mysql strftime("%%Y-%%m",obj) # 針對sqlite