簡體   English   中英

使用exists()和values_list()緩存Django查詢集

[英]Django queryset caching with exists() and values_list()

比方說,我正在嘗試將所有名為John個人資料的名稱更改為Mike

queryset = Profile.objects.filter(name='John')

方法一:

if queryset:
    queryset.update(name='Mike')
    logger.info(f'Updated the following profiles: {queryset.values_list('id', flat=True)}')

方法二:

if queryset.exists():
    queryset.update(name='Mike')
    logger.info(f'Updated the following profiles: {queryset.values_list('id', flat=True)}')

問題:更新名為John所有字段並記錄更新的記錄 ID 的最有效方法是什么?

方法 1 中,調用if queryset評估整個 queryset

方法 2 中,使用queryset.exists()進行查詢, queryset.update(...)調用也是如此。

最有效的方法是完全跳過條件if語句,只調用queryset.update(...) 調用的返回值將包括更新的行數,可能是0

為了測試差異,我們可以使用django.db.connection ,它會列出所有執行的查詢,以及它們花費了多長時間。

from django.db import connection, reset_queries

from django.contrib.models import User


def method_1(queryset):
    if queryset:
        queryset.update(first_name="Mike")

def method_2(queryset):
    if queryset.exists():
        queryset.update(first_name="Mike")

def method_3(queryset):
    queryset.update(first_name="Mike")


>>> connection.queries == []  # empty to start
True

>>> method_1(User.objects.all())
>>> [query["time"] for query in connection.queries]
['0.051', '0.126']

>>> reset_queries()

>>> method_2(User.objects.all())
>>> [query["time"] for query in connection.queries]
['0.001', '0.125']

>>> reset_queries()

>>> method_3(User.objects.all())
>>> [query["time"] for query in connection.queries]
['0.122']

如您所見, method_3僅使用單個查詢來執行更新,並且比其他方法更快。

如果您必須獲取每個更新的配置文件的 ID,您應該先查詢它,因為在更新行后,您將無法再次查詢。 您可以使用此結果來確定是否應該運行更新。

profile_ids_to_update = list(queryset.values_list('id', flat=True))
if profile_ids_to_update:
    queryset.update(name='Mike')
    logger.info(f'Updated the following profiles: {profile_ids_to_update}')

這將導致最多 2 個查詢,如果沒有要更新的行,則只有 1 個

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM