在Django中聚合save()吗?
我正在使用Django和sqlite数据库,但写入性能有点问题。将来我可能会换成一个“真正的”数据库,但目前我只能用sqlite。我觉得我的写入性能问题可能是因为我创建了很多行数据,每次我调用save()
的时候,数据库都会锁定、解锁并同步到磁盘上。
我该如何把很多个save()
操作合并成一次数据库操作呢?
4 个回答
我觉得你要找的方法是这个: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
装饰器就不能这样。
这里有一个重要的区别。根据提问者的问题,听起来他想要的是批量创建而不是批量保存。atomic
装饰器是保存时最快的解决方案,但不是创建时的最快方案。
在Django 1.6版本中新增了一个叫做 atomic 的功能,它是一个简单的接口,用来控制数据库的事务。
根据文档的说明,atomic可以作为一个 装饰器 使用:
from django.db import transaction
@transaction.atomic
def viewfunc(request):
# This code executes inside a transaction.
do_stuff()
也可以作为一个 上下文管理器 使用:
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中移除。
更新:commit_on_success
已经不再使用,并在 Django 1.8 中被移除了。请改用 transaction.atomic
。具体可以参考 Fraser Harris 的 回答。
其实这比你想象的要简单得多。在 Django 中,你可以使用事务。这些事务可以把多个数据库操作(特别是保存、插入和删除)合并成一个操作。我发现最简单的用法是 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_manually
和 transaction.commit()
来分批提交,但我很少需要这样做。