Django ORM 是 django 最強的功能之一。它抽象化了與資料庫互動的大部分複雜性,讓開發人員可以使用 Pythonic 語法而不是原始 SQL 來操作資料。所有這些 ORM 函數都會產生 SQL 查詢,如果處理不當,這些查詢可能會成為瓶頸。
本部落格重點介紹了使用 Django ORM 時的常見錯誤,並提供了保持查詢高效、可維護和高效能的技巧。
當您的程式碼觸發查詢以取得一組記錄,然後再次執行 N 個附加查詢來取得相關資料時,就會出現 N 1 查詢問題。
blogs = Blog.objects.all() # 1 Query for blog in blogs: print(blog.author.name) # N additional queries
在上面的範例中,在迴圈內造訪 blog.author.name 會導致 Django 單獨取得每個部落格的作者記錄,從而導致 N 個額外的查詢。
如何解決
對單一相關物件(例如,ForeignKey 或 OneToOneField)使用 select_lated,因為它執行 SQL JOIN 以在一個查詢中檢索主物件及其相關物件。對於多對多、多對一或反向關係,請使用 prefetch_lated,它在單獨的查詢中獲取相關數據,但在 Python 中有效地將它們組合起來,避免 N 1 問題。
# With select_related blogs = Blog.objects.select_related('author').all() # With prefetch_related authors = Author.objects.prefetch_related('blogs').all()
開發人員經常連結多個篩選器或使用 .all() ,然後對相同查詢集重複查詢:
blogs = Blog.objects.all() active_blogs = blogs.filter(is_archived=False) popular_blogs = blogs.filter(views__gte=1000)
儘管 Django 嘗試透過僅在需要時延遲評估查詢集來優化查詢集,但對相同查詢集資料重複呼叫過濾器仍然會導致對資料庫不必要的命中。
如何解決
在一條語句中組合篩選器允許 django 產生單一 SQL 查詢。
popular_active_blogs = Blog.objects.filter(is_archived=False, views__gte=1000)
有時我們只需要特定欄位而不是模型的所有欄位資料。在此期間使用 .values() 或 .values_list() 可以更有效率。
titles = Blog.objects.values('title') or titles = Blog.objects.values_list('title', flat=True) # values() returns a list of dictionaries. # values_list() can return tuples or flat values if flat=True is provided.
透過僅取得所需的列,可以減少從資料庫傳輸的資料量,從而提高效能。
重複呼叫 .aggregate() 或 .annotate() 可能會導致多次查詢。具有多個註解的複雜查詢可能會導致 SQL 查詢效率低下,從而可能導致繁重的資料庫操作。
# Example of multiple aggregate total_count = Blog.objects.aggregate(Count('id')) author_count = Blog.objects.aggregate(Count('author')) average_views = Blog.objects.aggregate(Avg('views'))
推薦
blogs = Blog.objects.all() # 1 Query for blog in blogs: print(blog.author.name) # N additional queries
索引使資料庫能夠快速定位和檢索數據,避免緩慢的全表掃描,從而提高查詢效能。索引優化了過濾、排序和連接等操作,使得對頻繁存取的欄位的查詢速度更快。頻繁查詢欄位上缺少資料庫索引會大大降低效能。
如何在 Django 中加入索引
# With select_related blogs = Blog.objects.select_related('author').all() # With prefetch_related authors = Author.objects.prefetch_related('blogs').all()
索引可以加快讀取速度,但會減慢寫入速度。因此,只對那些經常需要查詢的欄位建立索引。
當我們必須查詢計算成本昂貴或很少更改的資料時,請使用快取。即使快取 5 分鐘,也可以節省重複查詢、複雜計算和不經常更改的查詢。
blogs = Blog.objects.all() active_blogs = blogs.filter(is_archived=False) popular_blogs = blogs.filter(views__gte=1000)
有時,Django ORM 無法有效地表達複雜的查詢或批次操作。雖然 Django 提供 .extra() 或 .raw(),但原始 SQL 使用應該是最後的手段,因為它:
確保輸入已正確清理並保持原始 SQL 查詢可維護。
應用這些技巧,您將提高 Django 應用程式的效能,同時保持程式碼整潔和可維護。並建議在開發環境中使用 Django 偵錯工具列 來監控和分析執行的查詢數量、執行時間和 SQL 語句。
以上是需要修復的常見 Django ORM 錯誤的詳細內容。更多資訊請關注PHP中文網其他相關文章!