Django 資料層效能優化

2021-07-28 18:18:35 字數 3196 閱讀 1723

django資料層提供各種途徑優化資料的訪問,乙個專案大量優化工作一般是放在後期來做,早期的優化是「萬惡之源」,這是前人總結的經驗,不無道理。如果事先理解django的優化技巧,開發過程中稍稍留意,後期會省不少的工作量。

一 利用標準資料庫優化技術:

傳統資料庫優化技術博大精深,不同的資料庫有不同的優化技巧,但重心還是有規則的。在這裡算是題外話,挑兩點通用的說說:

索引,給關鍵的字段新增索引,效能能更上一層樓,如給表的關聯字段,搜尋頻率高的字段加上索引等。django建立實體的時候,支援給字段新增索引,具體參考django.db.models.field.db_index。按照經驗,django建立實體之前應該早想好錶的結構,盡量想到後面的擴充套件性,避免後面的表的結構變得面目全非。

使用適當字段型別,本來varchar就搞定的字段,就別要text型別,小細節別不關緊要,後頭資料量一上去,幾億幾億的資料,小字段很可能是大問題。

二 了解django的querysets:

了解django的querysets物件,對優化簡單程式有至關重要的作用。querysets是有快取的,一旦取出來,它就會在記憶體裡呆上一段時間,盡量重用它。舉個簡單的例子:

了解快取屬性:

>>> entry = entry.objects.get(id=1)

>>> entry.blog   # 部落格實體第一次取出,是要訪問資料庫的

>>> entry.blog   # 第二次再用,那它就是快取裡的實體了,不再訪問資料庫

但下面的例子就不一樣,

>>> entry = entry.objects.get(id=1)

>>> entry.authors.all()   # 第一次all函式會查詢資料庫

>>> entry.authors.all()   # 第二次all函式還會查詢資料庫

all,count exists是呼叫函式(需要連線資料庫處理結果的),注意在模板template裡的**,模板裡不允許括號,但如果使用此類的呼叫函式,一樣去連線資料庫的,能用快取的資料就別連線到資料庫去處理結果。還要注意的是,自定義的實體屬性,如果呼叫函式的,記得自己加上快取策略。

利用好模板的with標籤:

模板中多次使用的變數,要用with標籤,把它看成變數的快取行為吧。

使用querysets的iterator():

通常querysets先呼叫iterator再快取起來,當獲取大量的實體列表而僅使用一次時,快取行為會耗費寶貴的記憶體,這時iterator()能幫到你,iterator()只呼叫iterator而省去了快取步驟,顯著減少記憶體佔用率,具體參考相關文件。

三 資料庫的工作就交給資料庫本身計算,別用python處理:

1 使用 filter and exclude 過濾不需要的記錄,這兩個是最常用語句,相當是sql的where。

2 同一實體裡使用f()表示式過濾其他字段。

3 使用annotate對資料庫做聚合運算。

不要用python語言對以上型別資料過濾篩選,同樣的結果,python處理複雜度要高,而且效率不高, 白白浪費記憶體。

使用queryset.extra():

extra雖然擴充套件性不太好,但功能很強大,如果實體裡需要需要增加額外屬性,不得已時,通過extra來實現,也是個好辦法。

使用原生的sql語句:

如果發現django的orm已經實現不了你的需求,而extra也無濟於事的時候,那就用原生sql語句吧,用djangoango.db.connection.queries去實現你需要的東西。

四 如果需要就一次性取出你所需要的資料:

單一動作(如:同乙個頁面)需要多次連線資料庫時,最好一次性取出所有需要的資料,減少連線資料庫次數。此類需求推薦使用queryset.select_related() 和 prefetch_related()。

相反,別取出你不需要的東西,模版templates裡往往只需要實體的某幾個欄位而不是全部,這時queryset.values() 和 values_list(),對你有用,它們只取你需要的字段,返回字典dict和列表list型別的東西,在模版裡夠用即可,這可減少記憶體損耗,提高效能。

同樣queryset.defer()和only()對提高效能也有很大的幫助,乙個實體裡可能有不少的字段,有些字段包含很多元資料,比如部落格的正文,很多字元組成,django獲取實體時(取出實體過程中會進行一些python型別轉換工作),我們可以延遲大量元資料字段的處理,只處理需要的關鍵字段,這時queryset.defer()就派上用場了,在函式裡傳入需要延時處理的字段即可;而only()和defer()是相反功能。

使用queryset.count()代替len(queryset),雖然這兩個處理得出的結果是一樣的,但前者效能優秀很多。同理判斷記錄存在時,queryset.exists()比if queryset實在強得太多了。

當然一樣的結果,在快取裡已經存在,就別濫用count(),exists(),all()函式了。

五 懂減少資料庫的連線數:

使用 queryset.update() 和 delete(),這兩個函式是能批處理多條記錄的,適當使用它們事半功倍;如果可以,別一條條資料去update delete處理。

對於一次性取出來的關聯記錄,獲取外來鍵的時候,直接取關聯表的屬性,而不是取關聯屬性,如:

entry.blog.id

優於 entry.blog_id

善於使用批量插入記錄,如:

entry.objects.bulk_create([

entry(headline="python 3.0 released"),

entry(headline="python 3.1 planned")

])優於

entry.objects.create(headline="python 3.0 released")

entry.objects.create(headline="python 3.1 planned")

前者只連線一次資料庫,而後者連線兩次哦。

還有相似的動作需要注意的,如:多對多的關係,

my_band.members.add(me, my_friend)

優於my_band.members.add(me)

my_band.members.add(my_friend)

為什麼,批量處理的角度自己琢磨一下。

0 給主人留下些什麼吧!~~

Django的效能優化

一,利用標準資料庫優化技術 傳統資料庫優化技術博大精深,不同的資料庫有不同的優化技巧,但重心還是有規則的。在這裡算是題外話,挑兩點通用的說說 索引,給關鍵的字段新增索引,效能能更上一層樓,如給表的關聯字段,搜尋頻率高的字段加上索引等。django建立實體的時候,支援給字段新增索引,具體參考djang...

Django 資料庫訪問效能優化

1.使用標準的資料庫優化技術 在進行django資料庫訪問效能優化之前,首先應該使用標準的資料庫技術對其進行優化,比如給字段加索引,通過使用 django.db.models.field.db index 來給乙個django模型類的字段加索引,設定這個屬性欄位的field.db index tru...

Service層的效能優化

很多學j2ee方向的同學都接觸過s2sh,即傳統的三大框架,學習這三個經典技術的重點就是挖原理和細節,慢慢地我們就能形成一套思想,以幫助理解其他新框架和新技術。學習技術本身並不難,設計技術方案才是難點,為什麼要這麼設計,這樣設計的哲學依據又在哪?不難發現 struts2中控制層的action是多例的...