Django代碼性能優(yōu)化與Pycharm Profile使用詳解
前言
pycharm是python的一個(gè)商業(yè)的集成開發(fā)工具,本人感覺做python開發(fā)還是很好用的,django是一個(gè)很流行的python web開源框架,本文將通過實(shí)例代碼給大家介紹了關(guān)于Django代碼性能優(yōu)化與Pycharm Profile使用的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧
是一段導(dǎo)出數(shù)據(jù)月報(bào)的腳本,原先需要十幾秒,優(yōu)化后只需要1秒多。
Pycharm Profile
優(yōu)化第一步就是Profile,先看看慢在哪里。Pycharm自帶Profile工具,很方便。
拿一張官方圖說明一下。
圖表說明:
- 給出了函數(shù)調(diào)用關(guān)系。
- 紅色->黃綠色->綠色,顏色越深說明耗時(shí)越多。
- 右上角的“x數(shù)字”代表函數(shù)調(diào)用次數(shù)。
- Own代表該函數(shù)本身的耗時(shí),不包括調(diào)用子函數(shù);而Total包括調(diào)用子函數(shù)的耗時(shí)。還給出了耗時(shí)的百分比。
- 可以右鍵“jump to source”,跳到對(duì)應(yīng)的源碼。
有了Profile,剩下的事情就好辦了。
首先,看到了有個(gè)工具函數(shù)調(diào)用了9千多次,這個(gè)函數(shù)用到了nametupled,花了很多時(shí)間,于是把nametupled去掉,節(jié)省了好幾秒的時(shí)間。
開啟Django logger并設(shè)置DEBUG級(jí)別
繼續(xù)Profile,看到時(shí)間主要在ORM查詢數(shù)據(jù)庫那里。
這時(shí),開啟Django本身的logger,級(jí)別調(diào)到DEBUG,這樣就會(huì)打印出查詢的SQL語句。
N+1問題
首先意識(shí)到的是ORM查詢的N+1問題。
比如有個(gè)Order表,里面有個(gè)外鍵user_id是關(guān)聯(lián)User表.當(dāng)我們
for order in Order.objects.all(): order.user.id
的時(shí)候,Order.objects.all()只有1條sql語句,獲取Order表本身的字段到內(nèi)存,而不會(huì)將關(guān)聯(lián)的外鍵也獲取。
當(dāng)我們order.user_id的時(shí)候,不會(huì)觸發(fā)額外的sql查詢,而order.user.id的時(shí)候,會(huì)額外查詢User表。
for循環(huán)執(zhí)行了N次,就額外sql查詢了N次。故叫N+1問題。
解決N+1的方法:
- 如果是只用到id字段,則可以直接用user_id代替user.id
- select_related。將相關(guān)的表也一同查詢。select_related如果不傳參數(shù),表示查詢所有外鍵的表。
又節(jié)省了幾秒的時(shí)間。
只查詢需要的字段
繼續(xù)看log,發(fā)現(xiàn)sql查詢次數(shù)是減少了很多,然而sql查詢語句很長,看來是把所有字段都查詢出來。
然而我很多時(shí)候只需要某幾個(gè)字段而已,這樣全查出來就浪費(fèi)了。
解決方法:
- only()。只查詢想要的字段。比如Order.objects.only(‘user_id', ‘pay_date', ‘price')
- annotate()。 可指定虛擬字段,如果外鍵關(guān)聯(lián)的表只用到小部分字段,可以直接annotate過來。比如將User表的realname字段賦給Order表叫user_realname虛擬字段.這樣就不需要order.user.realname查詢,只需要order.user_realname來查詢,不用select_related把user表全部字段給取出來。Order.objects.annotate(user_realname=F(‘user__realname'))。注意還用到了F(),表示純數(shù)據(jù)庫層面的操作,不需要拉到python內(nèi)存進(jìn)行處理。
An F() object represents the value of a model field or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.
至此,將整段代碼的執(zhí)行時(shí)間減少到了1.5秒。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- 詳解Django中views數(shù)據(jù)查詢使用locals()函數(shù)進(jìn)行優(yōu)化
- Django serializer優(yōu)化類視圖的實(shí)現(xiàn)示例
- 淺談優(yōu)化Django ORM中的性能問題
- Django查詢優(yōu)化及ajax編碼格式原理解析
- 詳解Django配置優(yōu)化方法
- Django之使用celery和NGINX生成靜態(tài)頁面實(shí)現(xiàn)性能優(yōu)化
- django-rest-swagger的優(yōu)化使用方法
- 詳解Django的model查詢操作與查詢性能優(yōu)化
- Django程序的優(yōu)化技巧
相關(guān)文章
Python實(shí)現(xiàn)PDF轉(zhuǎn)為Excel的示例講解
這篇文章主要為大家詳細(xì)介紹了在Python中將PDF表格轉(zhuǎn)換為Excel文件的解決方案,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11Django添加favicon.ico圖標(biāo)的示例代碼
這篇文章主要介紹了Django添加favicon.ico圖標(biāo)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08python unix時(shí)間戳轉(zhuǎn)換毫秒的實(shí)現(xiàn)
Unix時(shí)間戳是一種常見的時(shí)間表示方式,本文主要介紹了python unix時(shí)間戳轉(zhuǎn)換毫秒的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01Python實(shí)現(xiàn)監(jiān)控遠(yuǎn)程主機(jī)實(shí)時(shí)數(shù)據(jù)的示例詳解
這篇文章主要為大家詳細(xì)介紹了Python如何使用Socket庫和相應(yīng)的第三方庫來監(jiān)控遠(yuǎn)程主機(jī)的實(shí)時(shí)數(shù)據(jù),比如CPU使用率、內(nèi)存使用率、網(wǎng)絡(luò)帶寬等,感興趣的可以了解一下2023-04-04Python3 filecmp模塊測(cè)試比較文件原理解析
這篇文章主要介紹了Python3 filecmp模塊測(cè)試比較文件原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03python實(shí)現(xiàn)m3u8格式轉(zhuǎn)換為mp4視頻格式
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)m3u8格式轉(zhuǎn)換為mp4視頻格式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02