在Django中聚合save()?

kdt*_*kdt 41 python sql sqlite django

我正在使用带有sqlite后端的Django,写性能是个问题.我可能会在某个阶段毕业到一个"适当的"数据库,但目前我仍然坚持使用sqlite.我认为我的写性能问题可能与我创建大量行的事实有关,并且大概每次我save()锁定,解锁和同步磁盘上的数据库.

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

Jud*_*ill 68

实际上这比你想象的要容易.您可以在Django中使用事务.这些批处理数据库操作(特别是保存,插入和删除)合并为一个操作.我发现最容易使用的是commit_on_success.基本上,您将数据库保存操作包装到函数中,然后使用transaction.atomic装饰器.

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()
Run Code Online (Sandbox Code Playgroud)

这将有巨大的速度提升.如果任何项目失败,您还可以获得回滚的好处.如果你有数百万的保存操作,那么你可能不得不使用commit_on_success和提交块,commit_on_success但我很少需要它.

希望有所帮助,

  • 对于那些现在遇到这个答案的人,现在不推荐使用`commit_on_success`.相反,用`atomic`替换它,这是新版本并具有相同的神奇效果! (50认同)
  • `atomic`参考:https://docs.djangoproject.com/en/dev/topics/db/transactions/#django.db.transaction.atomic (10认同)

Fra*_*ris 59

从Django 1.6开始,它是一个原子,一个控制数据库事务的简单API.从文档中逐字复制:

原子可用作装饰器:

from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()
Run Code Online (Sandbox Code Playgroud)

并作为上下文管理器:

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()
Run Code Online (Sandbox Code Playgroud)

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


Chr*_*lan 7

我认为这是您正在寻找的方法: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'),
])
Run Code Online (Sandbox Code Playgroud)

实际上,它看起来像:

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

Entry.objects.bulk_create(my_entries)
Run Code Online (Sandbox Code Playgroud)

根据文档,无论列表的大小如何(SQLite3上最多999个项目),该查询都将执行一个查询,这对于atomic装饰器来说是不可行的。

有一个重要的区别。从OP的问题看来,他似乎是试图批量创建而不是批量保存。该atomic装饰是最快的解决方案节省,而不是创造