用于多条记录的Django CRUD操作 - transaction.atomic与bulk_create

时间:2017-07-09 11:46:24

标签: django

我有一个Django 1.10模型和一个简单的模型:

我有一个简单的REST端点,用于测试目的:

@api_view(['POST'])
@transaction.atomic
def r_test(request):
    for record in request.data:
        serializer = TestSerializer(data = record)
        if serializer.is_valid():
           serializer.save()

...执行100条记录需要9秒(太慢)。

如果我按以下方式重写它,它会立即执行。

@api_view(['POST'])
def r_test(request):
    obj_list = []
    for record in request.data:
       obj = Test(field1 = record['field1'])
       obj_list.append(obj)
    Test.objects.bulk_create(obj_list)

令我烦恼的是,我已经阅读了很多来源,将函数包装到事务中(我通过添加装饰器@transaction.atomic来完成)会在多个操作的情况下显着改善插入操作。但我现在无法看到这一点。

所以问题是,只有bulk_create()为插入大数据提供超快的速度,或者我在transaction.atomic做错了吗?

更新:此外,我的设置中ATOMIC_REQUESTS设置为True。顺便说一句,这可能是设置中出现了问题吗?比如说,Debug = True会阻碍Django在单个事务中执行查询吗?

更新2 我已尝试使用装饰器和with transaction.atomic():中的for循环。我仍然只能使用bulk_create()

观察即时执行

更新3 。我的数据库是MySQL

2 个答案:

答案 0 :(得分:3)

事务通常会加快插入过程。由于您已经处于rank <- map(letters[1:2], ~ grepl(.x, names(df), fixed = TRUE)) %>% pmap(c) %>% map(which) ind_chr <- data_frame(colnames = names(df), rank) %>% mutate(l = lengths(rank)) %>% filter(l > 0) %>% mutate(rank = unlist(map(rank, ~ .x[[1]]))) %>% arrange(rank) %>% pull(colnames) df[ind_chr] 的交易中,因此在使用ATOMIC_REQUESTS = True时您不会注意到有所不同。事务更快的主要原因是提交需要时间。没有事务,Django使用自动提交模式,因此每个查询都会导致提交。

在性能方面,交易不是一个神奇的子弹。您仍在执行100次查询,并向数据库进行100次往返。即使您的数据库在同一系统上运行,也需要一些时间。 @transaction.atomic()发挥作用的地方。它执行单个查询以一次插入所有数据。您刚刚为自己保存了99次数据库往返。这比交易引起的任何加速都要重要。

答案 1 :(得分:1)

djangorestframework,对吗?我认为你应该首先改进你的api功能:

def r_test(request):
    serializer = TestSerializer(data=request.data, many=True)
    if serializer.is_valid():
       serializer.save()

再试一次。