Django - 有效地批量创建继承的模型

时间:2014-12-30 19:55:01

标签: mysql python-2.7 inheritance django-models database-performance

Python 2.7.9 Django 1.7 MySQL 5.6

我想填充属于多个类的一大堆对象实例,将它们堆叠成单个create() - 类似查询,打开数据库连接,执行查询,然后关闭。我的主要动机是性能,但代码紧凑性也是一个优势。

bulk_create()的功能似乎正是我想要的,但我违反了here列出的至少一个警告,即

  

它不适用于多对多关系。

  

它不适用于多表继承方案中的子模型。

这些限制也在the source code中描述:

# So this case is fun. When you bulk insert you don't get the primary
# keys back (if it's an autoincrement), so you can't insert into the
# child tables which references this. There are two workarounds, 1)
# this could be implemented if you didn't have an autoincrement pk,
# and 2) you could do it by doing O(n) normal inserts into the parent
# tables to get the primary keys back, and then doing a single bulk
# insert into the childmost table. Some databases might allow doing
# this by using RETURNING clause for the insert query. We're punting
# on these for now because they are relatively rare cases.

但是当我尝试它时返回的错误是泛型

  

ValueError:无法批量创建继承的模型

我的模型显然不包含任何多对多字段或外键。我不完全清楚他们所指的是多表继承方案,所以我不确定这是不是我的问题。我希望我可以使用看起来像这样的结构,但后来我得到了一般错误,所以没有骰子:

child class with OneToOneField---\
                                  \   
child class with OneToOneField----->---concrete parent class
                                  /
child class with OneToOneField---/

就源代码中提出的变通方法而言,#1对我来说不是一个选项,#2看起来并不吸引人,因为我认为它会牺牲我正在寻求的性能提升。

在处理这样的继承时是否有其他可以模拟bulk_create()的变通办法并且不会放弃性能上的提升?我需要回到原始SQL吗?我不介意为每个子对象类型创建单独的集合并执行单独的INSERT / create()

1 个答案:

答案 0 :(得分:9)

我确定的解决方法是将我收集的所有create()包裹在with transaction.atomic():中。通过在所有Python都返回之前不打开任何数据库连接或执行任何查询,这大大减少了运行时间。

缺点可能是如果遇到任何错误,则回滚所有更改并且数据库不受影响。这可以通过将create()分成批次并在每个批次周围打开和关闭事务来解决。 (在我的情况下,这不是理想的行为,因为我想要所有数据或者没有数据。)