使用Django导入10000份XLSX文件到MySQL的性能优化问题咨询
XLSX批量导入MySQL性能优化方案
现有代码核心瓶颈
当前实现的性能损耗主要集中在四个方面:
- 单线程串行处理1万份文件,CPU和IO资源都没有被充分利用
openpyxl默认加载全量内容(含格式、公式),逐单元格读取的效率极低- ORM单条插入数据,每一条记录都对应一次数据库请求+自动提交,数据库IO开销爆炸
- 直接在Web接口同步处理大批量任务,本身就存在超时风险,也没有横向扩展能力
分阶段优化方案
1. 第一阶段(实现难度最低,性能提升最明显,预计提效10倍以上)
- 替换数据库写入逻辑:
删掉所有单条Model.objects.create()+save()的写法,改用Django ORM的bulk_create()批量插入。每类表先把当前文件/当前批次的所有记录对象攒到列表里,处理完一个批次后一次性提交插入,数据库请求次数直接降低2-3个数量级。 - 优化openpyxl加载逻辑:
加载工作簿时开启只读+纯数据模式:wb_obj = openpyxl.load_workbook(file, read_only=True, data_only=True),跳过格式解析、公式计算等非必要步骤,加载速度可以提升3-5倍。
批量读取单元格:用iter_rows()/iter_cols()一次性读取指定范围内的所有单元格值,不要逐次调用working_sheet[坐标].value取值,减少对象访问开销。 - 修复冗余代码:
Model.objects.create()方法本身就会执行保存逻辑,后面额外调用的.save()完全多余,可以直接删除;同时修复Sheet2逻辑中未定义的create_assay、property_group、property_name变量bug。
2. 第二阶段(预计提效5-8倍)
- 架构调整:不要在Web接口同步处理1万份文件,改用异步任务架构,用Celery+消息队列把文件处理任务拆分为多个子任务异步执行,避免接口超时,同时支持横向扩展。
- 引入并发处理:文件处理是CPU+IO混合密集型任务,按CPU核心数开启对应数量的多进程Worker并行处理,处理速度可以接近线性提升,比如8核心机器就能提升7倍左右的处理速度。可以把1万份文件按每100份拆分为一个子任务,分发到不同Worker并行处理。
3. 第三阶段(极限优化,预计提效2-3倍)
- 临时关闭MySQL对应表的非必要索引、约束,全量导入完成后再重建,减少写入时的索引更新开销。
- 数据量特别大的场景可以直接用MySQL原生的
LOAD DATA INFILE能力:先把提取到的结构化数据存为临时CSV文件,直接调用MySQL命令批量导入,比ORM批量插入还要快2-3倍。 - 可以替换openpyxl为更快的Excel解析库,比如用pandas的read_excel批量读取,或者调用libreoffice把XLSX转换为CSV后再解析,解析速度可以再提升1-2倍。
完成前两个阶段的优化后,1万份文件的处理时间基本可以压缩到5-10分钟的预期范围内。
内容的提问来源于stack exchange,提问作者nerd_geek365
相关产品推荐
相关产品推荐

