首頁 後端開發 Python教學 使用 AppSignal 在 Django 中尋找並修復 N ueries

使用 AppSignal 在 Django 中尋找並修復 N ueries

Dec 22, 2024 pm 09:10 PM

在本文中,您將了解 N 1 查詢、如何使用 AppSignal 檢測它們,以及如何修復它們以顯著加快 Django 應用程式的速度。

我們將從理論方面開始,然後轉向實際範例。實際範例將反映您在生產環境中可能遇到的場景。

讓我們開始吧!

什麼是 N 1 查詢?

N 1 查詢問題是與資料庫互動的 Web 應用程式中普遍存在的效能問題。這些查詢可能會導致嚴重的瓶頸,並且隨著資料庫的成長而加劇。

當您檢索物件集合,然後存取集合中每個項目的相關物件時,就會出現問題。例如,取得書籍清單需要單一查詢(1 個查詢),但存取每本書的作者會觸發每個項目的額外查詢(N 個查詢)。

在資料庫中建立或更新資料時也可能會出現 N 1 問題。例如,透過循環迭代來單獨建立或更新對象,而不是使用bulk_create() 或bulk_update() 等方法,可能會導致過多的查詢。

N 1 查詢效率極低,因為執行大量小查詢比將操作合併為更少、更大的查詢要慢得多,而且更耗費資源。

Django 的預設 QuerySet 行為可能會無意中導致 N 1 問題,特別是如果您不知道 QuerySet 是如何運作的。 Django 中的查詢集是惰性的,這表示在對查詢集求值之前不會執行任何資料庫查詢。

先決條件

確保您擁有:

  • Python 3.9 和 Git 安裝在本機上
  • 支援 AppSignal 的作業系統
  • AppSignal 帳號

注意:此專案的原始程式碼可以在 appsignal-django-n-plus-one GitHub 儲存庫中找到。

項目設定

我們將使用圖書管理網路應用程式。該 Web 應用程式旨在演示 N 1 查詢問題以及如何解決它。

先複製 GitHub 儲存庫的基礎分支:

$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \
    --single-branch --branch base && cd appsignal-django-n-plus-one
登入後複製
登入後複製
登入後複製
登入後複製

接下來,建立並啟動虛擬環境:

$ python3 -m venv venv && source venv/bin/activate
登入後複製
登入後複製
登入後複製
登入後複製

安裝要求:

(venv)$ pip install -r requirements.txt
登入後複製
登入後複製
登入後複製

遷移並填入資料庫:

(venv)$ python manage.py migrate
(venv)$ python manage.py populate_db
登入後複製
登入後複製

最後,啟動開發伺服器:

(venv)$ python manage.py runserver
登入後複製

開啟您最喜歡的網頁瀏覽器並導航至 http://localhost:8000/books。 Web 應用程式應從資料庫傳回包含 500 本書的 JSON 清單。

Django 管理網站可透過 http://localhost:8000/admin 存取。管理員憑證是:

user: username
pass: password
登入後複製

為 Django 安裝 AppSignal

要在 Django 專案上安裝 AppSignal,請依照官方文件操作:

  • AppSignal Python 安裝
  • AppSignal Django 工具
  • AppSignal SQLite 工具

透過重新啟動開發伺服器確保一切正常:

$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \
    --single-branch --branch base && cd appsignal-django-n-plus-one
登入後複製
登入後複製
登入後複製
登入後複製

您的應用程式應自動向 AppSignal 發送演示錯誤。從此時起,您的所有錯誤都會傳送到 AppSignal。此外,AppSignal 將監控您應用程式的效能並偵測任何問題。

網路應用程式邏輯

修正 N 1 查詢的先決條件是了解應用程式的資料庫架構。密切注意模型的關係:它們可以幫助您找出潛在的 N 1 問題。

型號

Web 應用程式有兩個模型 - 作者和書籍 - 它們共享一對多 (1:M) 關係。這意味著每本書都與一個作者相關聯,而一個作者可以連結到多本書。

兩個模型都有一個 to_dict() 方法,用於將模型實例序列化為 JSON。最重要的是,Book 模型使用深度序列化(序列化書籍以及書籍的作者)。

模型在 books/models.py 中定義:

$ python3 -m venv venv && source venv/bin/activate
登入後複製
登入後複製
登入後複製
登入後複製

然後它們在 books/admin.py 中註冊 Django 管理站點,如下所示:

(venv)$ pip install -r requirements.txt
登入後複製
登入後複製
登入後複製

請注意,AuthorAdmin 使用 BookInline 在作者的管理頁面中顯示作者的書籍。

意見

網路應用程式提供以下端點:

  1. /books/ 回傳書籍清單
  2. /books// 回傳特定書籍
  3. /books/by-authors/ 傳回按作者分組的書籍清單
  4. /books/authors/ 返回作者列表
  5. /books/authors// 回傳特定作者

如果您正在執行開發網頁伺服器,則可以點擊上面的連結。

它們在 books/views.py 中定義如下:

(venv)$ python manage.py migrate
(venv)$ python manage.py populate_db
登入後複製
登入後複製

太棒了,您現在知道網頁應用程式是如何運作的!

在下一節中,我們將對我們的應用程式進行基準測試,以使用 AppSignal 檢測 N 1 個查詢,然後修改程式碼以消除它們。

使用 AppSignal 偵測 Django 應用程式中的 N 1 查詢

使用 AppSignal 檢測效能問題很容易。您所要做的就是像平常一樣使用/測試應用程式(例如,透過存取所有端點並驗證回應來執行最終用戶測試)。

當某個端點被命中時,AppSignal 將為其建立一份效能報告,並將所有相關存取分組在一起。每次訪問都將作為樣本記錄在端點的報告中。

偵測檢視中的 N 1 個查詢

首先,訪問您應用程式的所有端點以產生效能報告:

  1. /書籍/
  2. /books//
  3. /書籍/作者/
  4. /書籍/作者/
  5. /books/authors//

接下來,讓我們使用 AppSignal 儀表板來分析慢速端點。

範例 1:一對一關係 (select_lated())

導覽至您的 AppSignal 應用程式並選擇 效能 >側邊欄上的問題清單。然後按一下平均值 以平均回應時間降序對問題進行排序。

Find and Fix N ueries in Django Using AppSignal

點擊最慢的端點(books/)查看其詳細資訊。

Find and Fix N ueries in Django Using AppSignal

查看最新範例,我們可以看到該端點在 1090 毫秒內回傳回應。群組細分顯示 SQLite 需要 651 毫秒,而 Django 需要 439 毫秒。

這表示有問題,因為像這樣簡單的端點不應該花費那麼長的時間。

要獲取有關所發生事件的更多詳細信息,請選擇側邊欄中的範例,然後選擇最新範例。

Find and Fix N ueries in Django Using AppSignal

向下捲動到事件時間軸以查看執行了哪些 SQL 查詢。

Find and Fix N ueries in Django Using AppSignal

將滑鼠停留在 query.sql 文字上會顯示實際的 SQL 查詢。

執行了超過 1000 個查詢:

$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \
    --single-branch --branch base && cd appsignal-django-n-plus-one
登入後複製
登入後複製
登入後複製
登入後複製

這些是 N 1 個查詢的明顯標誌。第一個查詢取得一本書 (1),隨後的每個查詢取得該書的作者詳細資料 (N)。

要修復它,請導航至 books/views.py 並修改 book_list_view(),如下所示:

$ python3 -m venv venv && source venv/bin/activate
登入後複製
登入後複製
登入後複製
登入後複製

透過利用 Django 的 select_lated() 方法,我們在初始查詢中選擇附加的相關物件資料(即作者)。 ORM 現在將利用 SQL 連接,最終查詢將如下所示:

(venv)$ pip install -r requirements.txt
登入後複製
登入後複製
登入後複製

等待開發伺服器重新啟動並重新測試受影響的端點。

Find and Fix N ueries in Django Using AppSignal

再次進行基準測試後,回應時間從 1090 減少到 45,查詢數量從 1024 減少到 2。分別提高了 24 倍和 512 倍。

範例 2:多對一關係 (prefetch_lated())

接下來,讓我們來看看第二慢的端點(books/by-authors/)。

像我們在上一個步驟中所做的那樣使用儀表板來檢查端點的 SQL 查詢。您會注意到此端點有類似但不太嚴重的 N 1 模式。

這個端點的效能較不嚴重,因為 Django 夠聰明,可以快取頻繁執行的 SQL 查詢,也就是重複取得一本書的作者。查看官方文件以了解有關 Django 快取的更多資訊。

讓我們利用 books/views.py 中的 prefetch_lated() 來加速端點:

$ git clone git@github.com:duplxey/appsignal-django-n-plus-one.git \
    --single-branch --branch base && cd appsignal-django-n-plus-one
登入後複製
登入後複製
登入後複製
登入後複製

在上一節中,我們使用 select_lated() 方法來處理一對一關係(每本書都有一個作者)。然而,在本例中,我們正在處理一對多關係(一個作者可以擁有多本書),因此我們必須使用 prefetch_lated()。

這兩種方法的區別在於 select_lated() 工作在 SQL 級別,而 prefetch_lated() 則在 Python 級別進行最佳化。後一種方法也可以用於多對多關係。

有關更多信息,請查看 Django 關於 prefetch_lated() 的官方文檔。

基準測試後,回應時間從 90 毫秒減少到 44 毫秒,查詢數量從 32 減少到 4。

在 Django Admin 中偵測 N 1 個查詢

在 Django 管理網站中發現 N 1 個查詢的工作原理類似。

首先,登入您的管理網站並產生績效報告(例如,建立一些作者或書籍,更新和刪除它們)。

接下來,導覽到您的 AppSignal 應用程式儀表板,這次由管理員過濾問題:

Find and Fix N ueries in Django Using AppSignal

就我而言,兩個最慢的端點是:

  1. /管理/登入
  2. /admin/books/author/

我們無法對 /admin/login 做太多事情,因為它完全由 Django 處理,所以讓我們專注於第二個最慢的端點。檢查它會發現 N 1 查詢問題。每本書都會單獨取得作者。

要解決此問題,請重寫 BookInline 中的 get_queryset() 以在初始查詢中取得作者詳細資訊:

$ python3 -m venv venv && source venv/bin/activate
登入後複製
登入後複製
登入後複製
登入後複製

再次進行基準測試並驗證查詢數量是否有減少。

總結

在這篇文章中,我們討論了使用 AppSignal 檢測和修復 Django 中的 N 1 個查詢。

利用您在這裡學到的知識可以幫助您大幅加快 Django Web 應用程式的速度。

要記住的兩個最重要的方法是 select_lated() 和 prefetch_lated()。第一個用於一對一關係,第二個用於一對多和多對多關係。

編碼愉快!

P.S.如果您想在 Python 文章發布後立即閱讀,請訂閱我們的 Python Wizardry 時事通訊,不錯過任何一篇文章!

以上是使用 AppSignal 在 Django 中尋找並修復 N ueries的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1660
14
CakePHP 教程
1417
52
Laravel 教程
1311
25
PHP教程
1261
29
C# 教程
1234
24
Python vs.C:申請和用例 Python vs.C:申請和用例 Apr 12, 2025 am 12:01 AM

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。Python以简洁和强大的生态系统著称,C 则以高性能和底层控制能力闻名。

Python:遊戲,Guis等 Python:遊戲,Guis等 Apr 13, 2025 am 12:14 AM

Python在遊戲和GUI開發中表現出色。 1)遊戲開發使用Pygame,提供繪圖、音頻等功能,適合創建2D遊戲。 2)GUI開發可選擇Tkinter或PyQt,Tkinter簡單易用,PyQt功能豐富,適合專業開發。

2小時的Python計劃:一種現實的方法 2小時的Python計劃:一種現實的方法 Apr 11, 2025 am 12:04 AM

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

您可以在2小時內學到多少python? 您可以在2小時內學到多少python? Apr 09, 2025 pm 04:33 PM

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

Python與C:學習曲線和易用性 Python與C:學習曲線和易用性 Apr 19, 2025 am 12:20 AM

Python更易學且易用,C 則更強大但複雜。 1.Python語法簡潔,適合初學者,動態類型和自動內存管理使其易用,但可能導致運行時錯誤。 2.C 提供低級控制和高級特性,適合高性能應用,但學習門檻高,需手動管理內存和類型安全。

Python和時間:充分利用您的學習時間 Python和時間:充分利用您的學習時間 Apr 14, 2025 am 12:02 AM

要在有限的時間內最大化學習Python的效率,可以使用Python的datetime、time和schedule模塊。 1.datetime模塊用於記錄和規劃學習時間。 2.time模塊幫助設置學習和休息時間。 3.schedule模塊自動化安排每週學習任務。

Python:探索其主要應用程序 Python:探索其主要應用程序 Apr 10, 2025 am 09:41 AM

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

Python:自動化,腳本和任務管理 Python:自動化,腳本和任務管理 Apr 16, 2025 am 12:14 AM

Python在自動化、腳本編寫和任務管理中表現出色。 1)自動化:通過標準庫如os、shutil實現文件備份。 2)腳本編寫:使用psutil庫監控系統資源。 3)任務管理:利用schedule庫調度任務。 Python的易用性和豐富庫支持使其在這些領域中成為首選工具。

See all articles