Django4.0 數(shù)據(jù)庫訪問優(yōu)化-不要檢索你不需要的東西

2022-03-16 18:02 更新

使用 QuerySet.values() 和 values_list()

當(dāng)你只想得到字典或列表的值,并且不需要 ?ORM ?模型對象時,可以適當(dāng)使用 ?values()? 。這些對于替換模板代碼中的模型對象非常有用——只要你提供的字典具有與模板中使用時相同的屬性就行。

使用 QuerySet.defer() 和 only()

如果你明確不需要這個數(shù)據(jù)庫列(或在大部分情況里不需要),使用 ?defer()? 和 ?only()? 來避免加載它們。注意如果你使用它們,?ORM ?將必須在單獨的查詢中獲取它們,如果你不恰當(dāng)?shù)氖褂茫瑫屖虑樽兊迷愀狻?br>不要在沒有分析的情況下過分使用延遲字段,因為數(shù)據(jù)庫必須從磁盤中讀取結(jié)果中單行的大部分非文本、非VARCHAR數(shù)據(jù),即使它最終只使用的幾列。當(dāng)你不想加載許多文本數(shù)據(jù)或需要大量處理來轉(zhuǎn)換回 Python的字段, ?defer()? 和 ?only()? 方法最有用??傊?,先分析,再優(yōu)化。

使用 QuerySet.contains(obj)

如果您只想找出 obj 是否在查詢集中,而不是 obj 在查詢集中。

使用 QuerySet.count()

如果你只想計數(shù),不要使用 ?len(queryset)?。

使用 QuerySet.exists()

若你只想要確認(rèn)是否有至少存在一項滿足條件的結(jié)果,而不是? if queryset?。

不要過度使用 contains()、count() 和 exists()

如果你需要查詢集中的其他數(shù)據(jù),請立即對其進(jìn)行評估。

假設(shè) Group 模型與 User 具有多對多關(guān)系,則以下代碼是最佳的:

members = group.members.all()

if display_group_members:
    if members:
        if current_user in members:
            print("You and", len(members) - 1, "other users are members of this group.")
        else:
            print("There are", len(members), "members in this group.")

        for member in members:
            print(member.username)
    else:
        print("There are no members in this group.")

這是最佳的,因為:

  • 由于 ?QuerySet ?是惰性的,因此如果 ?display_group_members? 為 ?False?,則不會進(jìn)行數(shù)據(jù)庫查詢。
  • 將 ?group.members.all()? 存儲在 ?members ?變量中可以重用其結(jié)果緩存。
  • ?if members?: 導(dǎo)致 ?QuerySet.__bool__()? 被調(diào)用,這導(dǎo)致 ?group.members.all()? 查詢在數(shù)據(jù)庫上運行。 如果沒有任何結(jié)果,它將返回 ?False?,否則返回 ?True?。
  • ?if current_user in members?:檢查用戶是否在結(jié)果緩存中,因此不會發(fā)出額外的數(shù)據(jù)庫查詢。
  • ?len(members)? 的使用調(diào)用了 ?QuerySet.__len__()?,重用了結(jié)果緩存,因此再次沒有發(fā)出數(shù)據(jù)庫查詢。
  • ?for member?循環(huán)遍歷結(jié)果緩存。

使用 QuerySet.update() 和 delete()

如果要設(shè)置一些值并單獨保存它們,而不是檢索對象,那么可以通過 ?QuerySet.update()? 使用批量 SQL ?UPDATE ?語句。類似地,盡可能使用批量刪除( ?bulk deletes? )。
注意,盡管這些批量更新方法不會調(diào)用單獨實例的 ?save()? 或 ?delete()? 方法,這意味著你為這些方法添加的任何自定義行為都不會執(zhí)行,包括來自正常數(shù)據(jù)庫對象信號( ?signals? )的任何內(nèi)容。

直接使用外鍵值

如果只需要外鍵值,那么使用已有對象上的外鍵值,而不是獲取所有相關(guān)對象并獲取它的主鍵。比如:

entry.blog_id

替換成:

entry.blog.id

如無需要,不要排序結(jié)果

排序是耗時的;對每個字段的排序是數(shù)據(jù)庫必須執(zhí)行的操作。如果模型有一個默認(rèn)排序( ?Meta.ordering? )并且不需要它,那么可以通過調(diào)用沒有參數(shù)的 ?order_by()? 在查詢集上刪除它。
添加索引到你的數(shù)據(jù)庫上可以幫助改進(jìn)排序性能。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號