我正在使用Django的一個sqlite後端,並寫性能是一個問題。我可能會在某個階段畢業到一個「適當」的數據庫,但目前我堅持使用sqlite。我認爲我的寫入性能問題可能與我創建大量行有關,並且大概每次我鎖定,解鎖和同步磁盤上的數據庫。在Django中彙總save()?
如何將大量的save()
調用集合到單個數據庫操作中?
我正在使用Django的一個sqlite後端,並寫性能是一個問題。我可能會在某個階段畢業到一個「適當」的數據庫,但目前我堅持使用sqlite。我認爲我的寫入性能問題可能與我創建大量行有關,並且大概每次我鎖定,解鎖和同步磁盤上的數據庫。在Django中彙總save()?
如何將大量的save()
調用集合到單個數據庫操作中?
其實這樣做比較容易做,然後你就會想。您可以在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_manually
和transaction.commit()
以塊形式提交它們,但我很少需要它。
希望幫助,
請問
這幾乎是神奇的。我包裝了一個隨機函數,它創建了很多記錄,並且它在SQLite中立即變得快幾倍。 – alberge 2011-06-24 20:02:40
對於那些現在運行此答案的用戶,現在不推薦使用'commit_on_success'。相反,用'atomic'替換它,這是新版本,並且將具有相同的魔法效果! – Pterosaur 2014-07-23 17:47:12
'原子'參考:https://docs.djangoproject.com/zh/dev/topics/db/transactions/#django.db.transaction.atomic – Paolo 2016-06-15 14:28:47
「如何將大量save()調用聚合到單個數據庫操作中?」
你不需要。 Django已經爲你管理一個緩存。試圖通過保存措施來改善數據庫緩存。
「寫入性能問題可能與我要創建大量的行的事實」
正確的。
SQLite很慢。它就是這樣兒的。查詢比其他數據庫更快。寫入很慢。
考慮更嚴重的架構變更。您是否在Web事務中加載行(即批量上傳文件並從這些文件加載數據庫)?
如果您在網絡交易中進行批量加載,請停止。你需要做更聰明的事情。使用celery或使用其他一些「批次」工具在後臺執行加載。
我們試圖限制自己在Web事務中進行文件驗證,並在用戶不等待他們的HTML頁面時執行加載。
雖然指出sqlite確實天生就是公平的由於它使用磁盤的方式而導致寫入緩慢,因此它不必是* this * slow:正如評論員所建議的那樣,我開始使用@commit_manually裝飾器並發現了一個非常實際的改進。 – kdt 2010-08-03 10:24:04
新的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中刪除。
http://stackoverflow.com/questions/1136106/efficent-way-to-insert-thousands-of-records-into-a-table-sqlite-python-django – 2010-08-03 09:53:46
@Tomasz - 感謝您的鏈接, @commit_manually裝飾器爲我提供了所需的性能改進。我已經把我的問題標記爲關閉,因爲我認爲另一個很好地覆蓋了它。 – kdt 2010-08-03 10:22:55
你知道,你實際上可以關閉你的問題,而不是簡單地投票結束。 – 2010-08-03 12:41:51