批量创建失败,行数为1百万

时间:2018-03-31 16:28:50

标签: python django python-3.x django-models

出于学习目的,我创建了包含10 000行的csv文件和包含100万行的第2个文件,每行4列。我们的想法是将数据最有效地添加到表中。 (我正在使用SQL数据库)

第一种方法 - @transaction.atomic

@transaction.atomic
def insert(request):
    data_reader = csv.reader(open(csv_filepathname), delimiter=',', quotechar='"')

    for row in data_reader:
        nela = Nela()  # my model name
        nela.name = row[0]
        nela.last = row[1]
        nela.almost = row[2]
        nela.number = row[3]

        nela.save()


insert(request)

1)对于10 000行,需要2.1006858348846436来插入数据

2)对于100万行,它大概是~220.xx秒

我的第二种方法是使用bulk_create()

def insert(request):

data_reader = csv.reader(open(csv_filepathname), delimiter=',', quotechar='"')
header = next(data_reader)
Nela.objects.bulk_create([Nela(name=row[0], last=row[1], almost=row[2], number=row[3]) for row in data_reader])

insert(request)

1)对于10 000行,它需要0.4592757225036621,这是很酷的,比使用@transaction.atomic

快4倍以上

2)然而,对于100万行,它失败了,它超出了SQL基础的限制。

有没有人知道为什么会出现这样的错误?

我一直在阅读django docs bulk_create,但除了关于SQL Lite batch_size的注释外,我找不到任何有用的东西。

1 个答案:

答案 0 :(得分:2)

问题是您创建并提供给bulk_create的百万个对象列表。即使您只是传入迭代器,Django也会将其转换为列表,以便在继续之前优化插入。解决方案是使用islice在Django之外进行自己的批处理。

from itertools import islice

data_reader = csv.reader(open(csv_filepathname), delimiter=',', quotechar='"')
header = next(data_reader)
batch_size = 10000
while True:
    batch = [Nela(name=row[0], last=row[1], almost=row[2], number=row[3])
        for row in islice(data_reader, batch_size)]
    if not batch:
        break
    Nela.objects.bulk_create(batch, batch_size)