在Django中使用不同ID进行批量更新的正确方法

时间:2015-01-31 02:55:49

标签: python sql django

例如,列acctipstatus,(acct是唯一的)的表格,大约有1000行需要更新为特定的ipstatus(例如11.11.11.11和伟大的),我注意到update似乎是一个不错的选择:Entry.objects.filter(acct=xxx).update(comments_on=False),但这1​​000行都有不同的{{} 1}},迭代会花费太多开销(实际上一次至少需要更新100k行),这是一种正确的方法吗?

2 个答案:

答案 0 :(得分:2)

您可以对任何属性进行过滤,因此如果可以编写描述要更新的对象集的查询,则可以使用更新。

Entry.objects.filter(attr1=yyy, attr2=zzz).update('11.11.11.11', 'great')

如果您拥有的是ids列表,您可以执行以下操作,但我不保证它会为您提供所需的性能:

Entry.objects.filter(acct__in=<list_of_accounts>).update('11.11.11.11', 'great')

答案 1 :(得分:0)

我担心使用filter().update()是唯一的方法。

为了提高批量操作的速度,我建议您将此批量更新包装到事务中:

from django.db import transaction

with transaction.atomic():
    for acct, ip, status in accounts_to_update:
        Entry.objects.filter(acct=acct).update(ip=ip, status=status)

更新:@ jessamyn-smith的想法非常棒! acct是唯一的ip / status对怎么样?如果按此对重新组合源列表,是否会减少查询次数?

accounts_to_update = [
    ('xxx', '1.2.3.4', 'great'),
    ('xxy', '1.2.3.4', 'fail'),
    ('xxz', '1.2.3.4', 'great'),
    ('xx0', '1.2.3.0', 'great'),
]

ip_status_dict = {}
for acct, ip, status in accounts_to_update:
    accounts = ip_status_dict.setdefault((ip, status), [])
    accounts.append(acct)

with transaction.atomic():
    for (ip, status), accounts in ip_status_dict.iteritems():
        Entry.objects.filter(acct__in=accounts).update(ip=ip, status=status)