私はDjangoをsqliteバックエンドで使用しています。書き込みパフォーマンスが問題です。ある段階で「適切な」dbに変更される可能性がありますが、今のところsqliteで動けなくなっています。私の書き込みパフォーマンスの問題は、おそらく私が多数の行を作成しているという事実に関連していると思います。おそらく、私がsave()
oneを実行するたびに、ディスク上のDBがロック、ロック解除、同期されます。
多数のsave()
呼び出しを1つのデータベース操作に集約するにはどうすればよいですか?
編集:_commit_on_success
_は廃止され、Django 1.8で削除されました。代わりに_transaction.atomic
_を使用してください。FraserHarrisの answer を参照してください。
実際、これはあなたが考えるよりも簡単です。 Djangoでは transactions を使用できます。これらのバッチデータベース操作(具体的には、保存、挿入、削除)を1つの操作にまとめます。最も使いやすいのは_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()
を使用してブロックでそれらをコミットする必要があるかもしれませんが、私はめったにそれを必要としませんでした。
お役に立てれば幸いです。
意志
Django 1.6 is atomic、DBトランザクションを制御するシンプルなAPI の時点での新機能)==。ドキュメントから逐語的にコピー:
atomicは decorator として両方使用できます:
_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で削除されます。
これはあなたが探している方法だと思います: 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
デコレータには言えません。
重要な違いがあります。 OPの質問から、彼はbulk saveではなくbulk createを試行されているようです。 atomic
デコレータはsavingの最速のソリューションですが、creatingのソリューションではありません。
「多数のsave()呼び出しを1つのデータベース操作に集約するにはどうすればよいですか?」
する必要はありません。 Djangoは既にキャッシュを管理しています。保存をいじくりまわしてDBのキャッシュを改善することはできません。
「書き込みパフォーマンスの問題は、おそらく私が大量の行を作成しているという事実に関連しています」
正しい。
SQLiteはかなり遅いです。そういうものだ。クエリは他のほとんどのDBよりも高速です。書き込みはかなり遅いです。
より深刻なアーキテクチャの変更を検討してください。 Webトランザクション中に行をロードしていますか(つまり、ファイルを一括アップロードし、それらのファイルからDBをロードしていますか)?
Webトランザクション内で一括読み込みを実行している場合は、停止してください。もっと賢くする必要があります。 celery を使用するか、他の「バッチ」機能を使用して、バックグラウンドでロードを実行します。
私たちは、Webトランザクションでのファイル検証に制限し、ユーザーがHTMLのページを待機していないときにロードを実行しようとします。