在Django中聚合save()s?

2024-04-19 18:25:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我将Django与sqlite后端一起使用,写性能是个问题。我可能在某个阶段毕业成为一个“合适的”数据库,但目前我还停留在sqlite上。我认为我的写性能问题可能与我正在创建大量行的事实有关,而且可能每次我save()创建一行时,它都在锁定、解锁和同步磁盘上的数据库。

如何将大量的save()调用聚合到单个数据库操作中?


Tags: django数据库sqlitesave性能阶段磁盘事实
3条回答

已编辑:commit_on_success已弃用,并已在Django 1.8中删除。改用transaction.atomic。见弗雷泽·哈里斯的answer

实际上这比你想象的要容易。您可以在Django中使用transactions。这些批处理数据库操作(特别是保存、插入和删除)集中到一个操作中。我发现最容易使用的是commit_on_success。实际上,您将数据库保存操作包装成一个函数,然后使用commit_on_success装饰器。

from django.db.transaction import commit_on_success

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

这将有一个巨大的速度增长。如果有任何项目失败,您还将获得回滚的好处。如果您有数百万个保存操作,那么您可能需要使用commit_manuallytransaction.commit()将它们提交到块中,但我很少需要这样做。

希望能帮上忙

威尔

我想这就是你要找的方法:https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-create

从文档复制的代码:

Entry.objects.bulk_create([
    Entry(headline='This is a test'),
    Entry(headline='This is only a test'),
])

实际上,它看起来像:

my_entries = list()
for i in range(100):
    my_entries.append(Entry(headline='Headline #'+str(i))

Entry.objects.bulk_create(my_entries)

根据这些文档,不管列表的大小(SQLite3上最多999个项),这都会执行一个查询,这对于atomic装饰器来说是不可能的。

有一个重要的区别。听起来,从操作人员的问题来看,他试图批量创建而不是批量保存。对于保存来说,atomicdecorator是最快的解决方案,但对于创建来说则不是。

Django 1.6的新版本是atomic, a simple API to control DB transactions。从文档中逐字复制:

原子既可用作decorator

from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

作为context manager

from django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():
        # This code executes inside a transaction.
        do_more_stuff()

传统的django.db.transaction函数autocommit()commit_on_success()commit_manually()已被弃用,并将在Django 1.8中删除。

相关问题 更多 >