【问题标题】:Django Unique Bulk InsertsDjango 独特的批量插入
【发布时间】:2013-02-22 02:21:35
【问题描述】:

我需要能够快速批量插入大量记录,同时仍确保数据库中的唯一性。要插入的新记录已经被解析,并且是唯一的。我希望有一种方法可以在数据库级别而不是在代码本身中强制执行唯一性。

我使用 MySQL 作为数据库后端。如果 django 在任何其他数据库中支持此功能,我可以灵活地更改后端,因为这是一个要求。

Django 中的批量插入不使用save 方法,那么我怎样才能一次插入几百到几千条记录,同时仍然尊重唯一字段和唯一一起字段?


我的模型结构,简化后如下所示:

class Example(models.Model):
    Meta:
        unique_together = (('name', 'number'),)

    name = models.CharField(max_length = 50)
    number = models.CharField(max_length = 10)
    ...
    fk = models.ForeignKey(OtherModel)

编辑:

数据库中不存在的记录应该被插入,已经存在的记录应该被忽略。

【问题讨论】:

  • 您的原始数据是什么形式的?如果是 csv,我想知道您是否可以遍历每个条目并以这种方式保存。

标签: django django-models django-database


【解决方案1】:

正如 miki725 所说,您当前的代码没有问题。 我假设您正在使用 bulk_create 方法。确实,在使用 bulk_create 时不会调用 save() 方法,但在 save() 方法内部并未强制执行字段的唯一性。当您使用 unique_together 时,一个 唯一约束 会在创建表时添加到 mysql 中的基础表:

姜戈:

unique_together = (('name', 'number'),)

MySQL:

UNIQUE KEY `name` (`name`,`number`)

因此,如果您使用任何方法(save、bulk_insert 甚至原始 sql)向表中插入一个值,您将从 mysql 获得此异常:

Duplicate entry 'value1-value2' for key 'name'

更新:

bulk_insert 的作用是创建一个大查询,用一个查询一次插入所有数据。因此,如果其中一个条目重复,则会引发异常并且不会插入任何数据。

1- 一种选择是使用 bulk_insert 的 batch_size 参数,并使其在多个批次中插入数据,这样如果其中一个失败,您只会错过该批次的其余数据。 (取决于插入所有数据的重要性以及重复条目的频率)

2- 另一种选择是在批量数据上编写一个 for 循环并逐个插入批量数据。这样,仅针对该行引发异常,并插入其余数据。这会每次都查询数据库,当然会慢很多。

3- 第三个选项是解除唯一约束,使用 bulk_create 插入数据,然后编写一个简单的查询来删除重复的行。

【讨论】:

  • 这还会插入其余的记录吗?
  • 不幸的是,我不能错过任何数据,每条记录都必须进入数据库。我目前正在做类似#2的事情,它的速度足以让我问这个问题。我曾考虑过#3,但这似乎根本无法扩展。每个批量插入可以是数十万条记录。
  • @NickCSE 我会选择#3。它没有任何可扩展性问题。 bulk_create 当然是可扩展的。删除重复行的查询也可以以有效的方式编写。 (不要为此使用 django)
  • @NickCSE 你的问题解决了吗?如果您在编写删除重复查询时遇到问题,可以在新问题中提出。
  • 不是真的,我还是觉得这个解决方案不可扩展。我将使用类似这样的临时数据库设置的变体进行一些测试,看看什么是有效的。
【解决方案2】:

Django 本身并不强制使用 unique_together 元属性。这是由数据库使用UNIQUE 子句强制执行的。您可以根据需要插入尽可能多的数据,并保证指定的字段是唯一的。如果不是,那么将引发异常(不确定是哪一个)。更多关于unique_together 的信息请参见docs

【讨论】:

    猜你喜欢
    • 2022-06-14
    • 2013-11-10
    • 2015-10-02
    • 2018-10-11
    • 2011-05-16
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多