2012-01-18 95 views
3

我試圖設計一個使用Django的ORM ontop MySQL的批量數據導入任務。通常情況下,我只是使用LOAD DATA INFILE,但是我批量導入的數據包含三個表以上的記錄,並且某些記錄可能已經存在,所以我必須檢查預先存在的記錄,創建或檢索其ID ,然後在創建或檢索其他記錄時使用此ID。選擇性交易管理與Django ORM

默認情況下,導入速率爲0.8rows/sec。非常可怕。我通過在受影響的表上運行DISABLE KEYS來設法將其提高到1.5rows/sec,但由於我有幾百萬行,這仍然太慢了。

有沒有關於加快Django的ORM批量導入的一般建議複雜的表關係

我正在考慮禁用Django的事務管理,以便在單個事務中包裝整個導入。但是,由於導入過程很長,導入過程會定期更新狀態模型以報告完成百分比。如果我將整個導入包裝在單個事務中,它將無法更新此狀態記錄。那麼是否有任何方法可以僅爲特定的一組模型禁用事務管理,並且仍然允許它提交一個單獨的模型?

我想這樣做:

from django.db import transaction 
transaction.enter_transaction_management() 
transaction.managed(True) 

from myapp.models import Status, Data 

status = Status.objects.get(id=123) 
try: 
    data = magically_get_data_iter() 
    for row in data: 
     d,_ = Data.objects.get_or_create(**data.keys()) 
     d.update(data) 
     d.save() # not actually visible in admin until the commit below 
     if not row.i % 100: 
      status.current_row = row.i 
      status.total_rows = row.total 
      # obviously doesn't work, but this should somehow actually commit 
      status.save(commit=True) 
finally: 
    transaction.commit() 

回答

3

我通過將批量更新的模型和模型存儲的狀態記錄到不同的數據庫,然後禁用事務管理,前者數據庫解決了這個。

例如我上面的例子的簡化:

django.db.transaction.enter_transaction_management(using='primary') 
django.db.transaction.managed(True, using='primary') 

i = 0 
for record in records: 
    i += 1 
    r = PrimaryDBModel(**record) 
    r.save() # This will no be committed until the end. 
    if not i % 100: 
     SecondaryDBModel.update() 
     status = SecondaryDBModel(id=123) 
     status.current_row = i 
     status.save() # This will committed immediately. 

django.db.transaction.commit(using='primary') 
django.db.transaction.leave_transaction_management(using='primary')