提问人:Stephen Milic 提问时间:11/16/2023 最后编辑:Stephen Milic 更新时间:11/16/2023 访问量:46
在 jsonfields 中递增的 Django 更新方法超级慢
Django update method for incrementing in jsonfields is super slow
问:
我有一个使用 json 字段的模型,虽然这在 99% 的时间里就像一个魅力,但我现在有一个有点烦人的问题,即执行时间。
我需要使用 Django 的 ORM 方法增加大量记录,我不知道如果数据库使用 json 字段以外的其他内容应该有多快,但基本上这里有一些我面临的时间示例:update
- JSON 字段中仅 +1 的 4000 条记录更新就需要 20 秒
- 6000 条记录更新花了将近 2 分钟
这些都是小的,我预计一些更新会有超过 100000 条记录,甚至可能达到 100 万条。
对于我正在做的事情的技术方面:
我在 jsonfield 值内使用范围来提取需要更新的记录,在获取我用来将其中一个 jsonfield 值递增 1 的查询集后,这运行得很好。filter
update
这种行为非常具体,可能不是最优化的,但这就是我现在所拥有的,为此,我使用 进行原始 sql 查询,作为参考,这里是生成所述查询的函数:RawSQL
def jsonfield_increment(field_name: str, key: str, increment_by: int = 1, operator: str = "+") -> RawSQL:
sql = f"""
jsonb_set(
{field_name},
'{{{key}}}',
(COALESCE({field_name}->>'{key}','12')::int {operator} {increment_by})::text::jsonb
)
"""
return RawSQL(sql, [])
这种方法基本上提取 inside 的值,然后递增它。key
field
然后,我只需在之前使用 过滤的查询集上运行该方法。update
field=jsonfield_increment(args)
所以这就是我想知道的,
有没有办法优化更新记录的方式?此更新需要经常运行。
我是否应该拆分查询集中每条X记录的更新并使用线程池保存每个块?
我应该使用其他方法而不是存储实例,然后使用?
update
bulk_update
我是否应该花时间完全重新设计这些 int 的存储方式而不使用 jsonfield ?
虽然最后一个听起来是最好的选择,但我有点害怕这样做
因为我在那里存储的东西有点动态,所以它需要一个整体
带有关系的新表,它最终可能会超过 100 个
millons 记录带有 like , , (必需的 jsonfield) 和 where parent would
是当前存储 int 的对象。索引可以使它变得更快,但在该表上写入可能需要一些时间。name
int
data
parent
如果有帮助,我可以尝试提供该方法生成的 SQL。update
答:
我会试着告诉你我会怎么做。我从 pandas 数据帧中读取了 json。Pandas 数据帧将数据传递给 Django ORM。 要将数据从 Pandas 传递到 ORM,我有 2 种可能的方法: 最好的方法是使用 sqlackemy,它是异步的,它非常适合我需要做的工作。我需要与可用的主机建立 SSH 连接。我需要在 setting.py 中配置 sqlackemy。 第二种使用 df.iterrows() 来迭代数据帧的行,并使用 bulk_create() 将它们加载到 ORM 模型中。 我没有考虑到我在 ORM 模型中有外键。它们在迭代时会减慢很多速度。
评论
update
评论
filter
filter
Model.objects.filter(**{f"field__{dyn_key_name}__range": interval})
update