【发布时间】:2021-11-10 06:26:45
【问题描述】:
我正在尝试批量更新大量记录(320 万条)。
这是我的模型:
class MyModel(models.Model):
stats = JSONField()
统计数据通常保存为:
{
"my_old_key": [{"hey": "Hello World"}]
}
我想更新它,以便只有键会改变它的值,最终统计信息看起来像这样(尽管已经有 "my_new_key" 的记录,所以最好以某种方式跳过这些记录):
{
"my_new_key": [{"hey": "Hello World"}]
}
我可以在 Python 中做到这一点,但它的工作速度真的很慢。我已经尝试使用来自 this link 的批处理方法处理约 10k 条记录,这样查询集就不会完全提取到内存中。最终解决方案如下所示:
def update_queryset(queryset) -> None:
for stat in queryset:
dictionary = stat.stats
if "my_old_key" in dictionary:
dictionary["my_new_key"] = dictionary.pop("my_old_key")
stat.save()
它确实有效,但不幸的是它运行得太慢了:(。
我曾想过根本不将它提取到 python 并纯粹在数据库 somewhat like this answer suggested 上工作,但没能成功。
关于如何加快速度/编写 RawSQL/使jsonb_set 方法起作用的任何建议?
编辑: 我事先过滤了查询集,以便跳过额外的 if 检查但无济于事。仍然工作缓慢..
queryset = MyModel.objects.filter(stats__has_key="my_old_key")
...
def update_queryset(queryset) -> None:
for stat in queryset:
dictionary = stat.stats
dictionary["my_new_key"] = dictionary.pop("my_old_key")
stat.save()
【问题讨论】:
-
你试过
transaction.atomic()吗? -
@codepylot 我刚刚做的,无论是用于包装整个
update_queryset方法还是save()调用,似乎都没有使它更快:(。 -
@EneP 我知道 bulk_update 但我不太确定如何按照我描述的方式将它与
JSONField一起使用。你能告诉我这是什么样子吗?
标签: python django postgresql django-rest-framework