2012-01-18 4 views
3

MySQLのDjangoのORMのontopを使用してバルクデータのインポートタスクを設計しようとしています。通常はLOAD DATA INFILEを使用しますが、一括インポートするデータには3つのテーブルのレコードが含まれています。レコードの一部はすでに存在する可能性がありますので、既存のレコードを確認したり、他のレコードを作成または取得するときにこの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') 
関連する問題