[英]Producing a list by summing results of 'values_list' in Django queryset
[英]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.