Django如何高效实现从JSON批量更新或创建1万至3万条数据库记录
Django 1-3万条数据批量Upsert(更新/插入)高效解决方案
你当前使用的第三方库django-bulk-update-or-create性能差的核心原因是底层实现没有走数据库原生UPSERT逻辑,存在大量逐行查询或者多次数据库交互的开销,是导致1.5万条数据耗时1小时的核心原因,可通过以下方案优化:
方案1:使用Django原生bulk_create+update_conflicts(优先推荐,改动最小,性能提升最明显)
- 适用Django版本:3.2及以上,支持所有主流关系型数据库(PostgreSQL/MySQL 8.0+/SQLite 3.35+)
- 核心优势:直接生成数据库原生UPSERT语句,全程仅1-2次数据库交互,无额外查询开销,2万条数据耗时通常在5秒以内
- 优化后的代码示例:
from django.db import transaction @transaction.atomic def update_data_in_db(data): objs = [] for item in data: try: # 注意:原代码存在模型类不一致错误,此处统一用你实际的模型类Currency objs.append(Currency( id=item['id'], name=item.get('name'), slug=item.get('slug'), )) except Exception as err: logger.exception(err) # 原生批量upsert,冲突时更新指定字段,batch_size按实际调整,推荐1000-2000 Currency.objects.bulk_create( objs, update_conflicts=True, update_fields=['name', 'slug'], unique_fields=['id'], batch_size=1000 ) return [obj.id for obj in objs]
- 注意事项:确保数据库中
id字段是唯一索引/主键,否则冲突检测不生效
方案2:原生SQL临时表批量Upsert(性能极致,适合更大数据量场景)
如果需要处理超过10万条数据,或者需要更高性能,可以直接通过Django游标执行数据库原生导入逻辑:
- 先创建临时表,结构和目标表一致
- 将所有待入库数据批量写入临时表(无索引写入速度极快)
- 执行单条UPSERT语句,将临时表数据一次性同步到目标表
- 删除临时表
- 该方案处理3万条数据通常耗时在1秒以内,比ORM方案快数倍
其他优化建议
- 入库前关闭数据库表的非必要索引,入库完成后再重建,可进一步提升写入速度
- 不要在循环中执行任何数据库查询操作,所有逻辑前置到内存中处理
- 如果使用MySQL,可以临时关闭
autocommit和unique_checks,入库完成后再恢复
内容的提问来源于stack exchange,提问作者Paul Bénêteau
相关产品推荐
相关产品推荐

