Django - SQL 批量 get_or_create 可能吗?

Posted

技术标签:

【中文标题】Django - SQL 批量 get_or_create 可能吗?【英文标题】:Django - SQL bulk get_or_create possible? 【发布时间】:2016-03-03 15:51:48 【问题描述】:

我正在使用 get_or_create 将对象插入数据库,但问题是一次执行 1000 个需要很长时间。

我尝试了 bulk_create,但它没有提供我需要的功能(创建重复项、忽略唯一值、不触发我需要的 post_save 信号)。

甚至可以通过自定义的 sql 查询批量执行 get_or_create 吗?

这是我的示例代码:

related_data = json.loads(urllib2.urlopen(final_url).read())

for item in related_data:

    kw = item['keyword']
    e, c = KW.objects.get_or_create(KWuser=kw, author=author)
    e.project.add(id)
    #Add m2m to parent project

related_data 包含 1000 行,如下所示:

["cmp":0,"ams":3350000,"cpc":0.71,"keyword":"apple.",
"cmp":0.01,"ams":3350000,"cpc":1.54,"keyword":"apple -10810"......]

KW 模型还发送我用来创建另一个父模型的信号:

@receiver(post_save, sender=KW)
def grepw(sender, **kwargs):
    if kwargs.get('created', False):
        id = kwargs['instance'].id
        kww = kwargs['instance'].KWuser
        # KeyO 
        a, b = KeyO.objects.get_or_create(defaults='keyword': kww, keyword__iexact=kww)
        KW.objects.filter(id=id).update(KWF=a.id)

这可行,但您可以想象一次处理数千行需要很长时间,甚至会导致我的小型服务器崩溃,我有哪些批量选项?

【问题讨论】:

【参考方案1】:

从 Django 2.2 开始,bulk_create 有一个 ignore_conflicts 标志。每the docs:

在支持它的数据库上(除 Oracle 之外的所有数据库),将 ignore_conflicts 参数设置为 True 会告诉数据库忽略插入任何违反约束的行(例如重复唯一值)的失败

【讨论】:

【参考方案2】:

如果我理解正确,“get_or_create”表示 Postgres 端的 SELECTINSERT

您有一个带有UNIQUE 约束或索引的表以及INSERT(如果还没有的话)的大量行,并获取新创建的ID 或SELECT 现有行的ID。并不像表面上看起来那么简单。并发写入负载,事情就更复杂了。

还有各种参数需要定义(如何准确处理冲突):

How to use RETURNING with ON CONFLICT in PostgreSQL?

【讨论】:

【参考方案3】:

这篇文章可能对你有用:

***.com/questions/3395236/aggregating-saves-in-django

请注意,答案建议使用已弃用的 commit_on_success 装饰器。它被 transaction.atomic 装饰器取代。文档在这里:

transactions

from django.db import transaction

@transaction.atomic
def lot_of_saves(queryset):
    for item in queryset:
        modify_item(item)
        item.save()

【讨论】:

以上是关于Django - SQL 批量 get_or_create 可能吗?的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy 是不是与 Django 的 get_or_create 等效?

SQLAlchemy 是不是与 Django 的 get_or_create 等效?

django - 使用 get_or_create 自动创建用户时设置用户权限

使用 User.objects.get_or_create() 在 django 中给出无效的密码格式?

覆盖Django get_or_create

与 iexact 一起使用时,Django get_or_create 无法设置字段