Django代碼性能優(yōu)化與Pycharm Profile使用詳解
前言
pycharm是python的一個商業(yè)的集成開發(fā)工具,本人感覺做python開發(fā)還是很好用的,django是一個很流行的python web開源框架,本文將通過實例代碼給大家介紹了關(guān)于Django代碼性能優(yōu)化與Pycharm Profile使用的相關(guān)內(nèi)容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧
是一段導出數(shù)據(jù)月報的腳本,原先需要十幾秒,優(yōu)化后只需要1秒多。
Pycharm Profile
優(yōu)化第一步就是Profile,先看看慢在哪里。Pycharm自帶Profile工具,很方便。
拿一張官方圖說明一下。
圖表說明:
- 給出了函數(shù)調(diào)用關(guān)系。
- 紅色->黃綠色->綠色,顏色越深說明耗時越多。
- 右上角的“x數(shù)字”代表函數(shù)調(diào)用次數(shù)。
- Own代表該函數(shù)本身的耗時,不包括調(diào)用子函數(shù);而Total包括調(diào)用子函數(shù)的耗時。還給出了耗時的百分比。
- 可以右鍵“jump to source”,跳到對應的源碼。
有了Profile,剩下的事情就好辦了。
首先,看到了有個工具函數(shù)調(diào)用了9千多次,這個函數(shù)用到了nametupled,花了很多時間,于是把nametupled去掉,節(jié)省了好幾秒的時間。
開啟Django logger并設置DEBUG級別
繼續(xù)Profile,看到時間主要在ORM查詢數(shù)據(jù)庫那里。
這時,開啟Django本身的logger,級別調(diào)到DEBUG,這樣就會打印出查詢的SQL語句。
N+1問題
首先意識到的是ORM查詢的N+1問題。
比如有個Order表,里面有個外鍵user_id是關(guān)聯(lián)User表.當我們
for order in Order.objects.all(): order.user.id
的時候,Order.objects.all()只有1條sql語句,獲取Order表本身的字段到內(nèi)存,而不會將關(guān)聯(lián)的外鍵也獲取。
當我們order.user_id的時候,不會觸發(fā)額外的sql查詢,而order.user.id的時候,會額外查詢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é)省了幾秒的時間。
只查詢需要的字段
繼續(xù)看log,發(fā)現(xiàn)sql查詢次數(shù)是減少了很多,然而sql查詢語句很長,看來是把所有字段都查詢出來。
然而我很多時候只需要某幾個字段而已,這樣全查出來就浪費了。
解決方法:
- 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)存進行處理。
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í)行時間減少到了1.5秒。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
Python實現(xiàn)PDF轉(zhuǎn)為Excel的示例講解
這篇文章主要為大家詳細介紹了在Python中將PDF表格轉(zhuǎn)換為Excel文件的解決方案,文中的示例代碼簡潔易懂,感興趣的小伙伴可以跟隨小編一起學習一下2023-11-11python unix時間戳轉(zhuǎn)換毫秒的實現(xiàn)
Unix時間戳是一種常見的時間表示方式,本文主要介紹了python unix時間戳轉(zhuǎn)換毫秒的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-01-01Python實現(xiàn)監(jiān)控遠程主機實時數(shù)據(jù)的示例詳解
這篇文章主要為大家詳細介紹了Python如何使用Socket庫和相應的第三方庫來監(jiān)控遠程主機的實時數(shù)據(jù),比如CPU使用率、內(nèi)存使用率、網(wǎng)絡帶寬等,感興趣的可以了解一下2023-04-04python實現(xiàn)m3u8格式轉(zhuǎn)換為mp4視頻格式
這篇文章主要為大家詳細介紹了python實現(xiàn)m3u8格式轉(zhuǎn)換為mp4視頻格式,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-02-02