Django轻量级“更新”海量数据集

Oli*_*Oli 1 python sql django postgresql orm

我有一个非常大的数据集,需要尽快更新。我进行了计算,最后列出了需要更新的内容:

\n\n
updates = [(instance_pk, value_to_update), (instance_pk, value_to_update), ..]\n
Run Code Online (Sandbox Code Playgroud)\n\n

模型始终相同,更新的列也是如此。

\n\n

过去我使用过 Django Bulk Update \xe2\x80\x94 并且我相当确定我可以在这里 \xe2\x80\x94 但即使这样也太过强大(因此做了太多的处理,因为它处理完整的实例)对于如此简单的写作,我需要快速完成。我有没有提到速度在这里很重要?

\n\n

Django 提供什么吗可以使这变得更容易而无需编写原始 SQL 的东西?

\n\n

PostgreSQL 10 是数据库(如果相关的话)。

\n\n
\n\n

我已经测试了原始 SQL,它的性能是可以预见的,但它看起来是这样的,所以你很清楚我想在 Django 中做什么。

\n\n
with connection.cursor() as c:\n    c.executemany(\n        'UPDATE app_model SET column_a = %s WHERE id = %s',\n        [(value_to_update, instance_pk), ...]\n    )\n
Run Code Online (Sandbox Code Playgroud)\n\n

可能有比执行许多更有效的 SQL(我认为这会抛出许多查询)。

\n

Oli*_*Oli 5

当 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), ...]
    )
Run Code Online (Sandbox Code Playgroud)

而且速度快得难以想象。我不认为情况会比这更好。