我有一个非常大的数据集,我需要尽快更新。我做了我的计算,并在最后有一个需要更新的事项列表:
updates = [(instance_pk, value_to_update), (instance_pk, value_to_update), ..]
模型在整个过程中都是一样的,正在更新的列。
过去我使用过Django Bulk Update - 而且我非常确定我能在这里 - 但即便如此,这样一个简单的过于强大(并因此处理太多的处理,因为它处理完整的实例)写道,我需要快速发生。我提到速度在这里很重要吗?
Django是否提供任何可以使这更容易,而无需编写原始SQL?
PostgreSQL 10是数据库,如果证明它是相关的。
我已经测试了原始SQL,这可以预见性能,但是这里看起来很像,所以你要清楚我在Django中尝试做什么。< / p>
with connection.cursor() as c:
c.executemany(
'UPDATE app_model SET column_a = %s WHERE id = %s',
[(value_to_update, instance_pk), ...]
)
可能有更高效的SQL而不是执行许多(我认为在一次交易中会抛出许多查询)。
答案 0 :(得分:2)
虽然Kos正在撰写他们的优秀答案,但我仍在努力改进原始SQL方法,只是为了加快速度。
cursor.executemany()
并不聪明。它只是立即执行大量查询。 PostsgreSQL有一个UPDATE FROM VALUES(..)
子句,但与它接口是很棘手的。值得庆幸的是,psycopg2有一个特殊的execute_values
用于制作这些值集,它们甚至记录了一个更新示例。
如果您正在使用psycopg2 + Postgres,Django会将您的原始psycopg2连接传回给您,所以这一切都非常容易使用:
from django.db import connection
from psycopg2.extras import execute_values
with connection.cursor() as c:
execute_values(
c,
'UPDATE app_model SET column_a = v.sid FROM (VALUES %s) as v (sid, bid) WHERE id = v.bid',
[(value_to_update, instance_pk), ...]
)
而且速度难以想象。我认为它不会比这更好。
答案 1 :(得分:1)
给定一个键值对列表,您可以通过几种方法在SQL中运行UPDATE:
UPDATE app_model SET column_a = %s WHERE id = %s
UPDATE app_model SET column_a = %s WHERE id = %s
UPDATE app_model SET column_a = %s WHERE id = %s
UPDATE app_model SET column_a = %s WHERE id = %s
这很容易在Django中表示:
for key, value in updates:
Model.objects.filter(id=key).update(column_a=value)
UPDATE app_model SET column_a = CASE
WHEN id = %s THEN %s
WHEN id = %s THEN %s
WHEN id = %s THEN %s
WHEN id = %s THEN %s
...
WHERE id IN (%s, %s, %s, %s, ...)
这应该更快,因为数据库可以更有效地找到所有行。查询最终将超长,我建议批量使用此方法(比如100或1000行,进行实验,看看会发生什么)。
在Django中,您可以via the ORM:
执行此操作Model.objects.filter(id__in=ids).update(
column_a=Case(
When(id=..., then=Value(...)),
When(id=..., then=Value(...)),
When(id=..., then=Value(...)),
When(id=..., then=Value(...)),
When(id=..., then=Value(...)),
...
)
)
或通过使用更好的API执行django-bulk-update的第三方a similar thing包。
注意:这是PostgreSQL特有的。其他数据库可能会提供其他类似的SQL扩展。
如果您可以制作包含要更新的所有data
对的表(key, value)
,那么您就可以使用优雅的单一查询方法:
UPDATE app_model
SET column_a = data.value
FROM data
WHERE app_model.id = data.key;
如果更简单,您还应该能够替换子查询,而不是表格。
无论如何,我还没有找到使用Django ORM构建UPDATE FROM
查询的方法,所以这需要在我能说的时候放弃原始SQL。