2012-01-18 92 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')