InsertManyAsync插入性能问题:9万条数据耗时约50分钟
批量插入9万条实体数据的性能优化方案
关键优化建议
- 关闭变更追踪:你当前调用
InsertManyAsync时第二个参数传了true,这会让EF Core为每个实体维护状态追踪,批量导入场景完全不需要这个功能,改成false能大幅减少内存占用和处理时间。 - 调整批次大小:除了100/500/1000,试试2000-5000的批次(注意数据库的语句长度或数据包限制,比如SQL Server的
max_allowed_packet),过大批次可能触发报错,需要根据数据库类型微调。 - 统一事务管理:把所有批次包在一个大事务里提交,避免每个批次单独开启提交事务的开销——但要注意大事务会增加数据库日志压力,需结合数据库配置调整。
- 改用原生数据库批量工具:如果ORM批量性能还是不达标,直接用数据库原生批量导入功能:
- SQL Server:用
SqlBulkCopy - MySQL:用
MySqlBulkCopy或LOAD DATA INFILE - PostgreSQL:用
COPY命令
原生工具的性能比ORM批量插入高一个数量级,9万条数据通常能在几分钟内完成。
- SQL Server:用
- 临时禁用约束与索引:插入前关闭非必要的外键约束、非聚集索引和触发器,插入完成后再重新启用——这些校验逻辑会在每批次插入时额外消耗资源。
- 简化实体映射:确保批量插入的实体没有加载不必要的导航属性,EF Core处理复杂关联会增加额外开销。
调整后的示例代码(关闭追踪+大事务)
int batchSize = 2000; int totalCount = nichoInvoices.Count(); int i = 1; var batches = nichoInvoices.Batch(batchSize); using var transaction = await _invManager.InvoiceRepository.Database.BeginTransactionAsync(); try { foreach (var batch in batches) { Logger.LogInformation($"Seeding Invoices {Math.Min(i * batchSize, totalCount)}/{totalCount}"); await _invManager.InvoiceRepository.InsertManyAsync(batch, false); i++; } await transaction.CommitAsync(); Logger.LogInformation($"End Seeding Invoices"); } catch (Exception ex) { await transaction.RollbackAsync(); Logger.LogError(ex, $"Seeding Invoices failed"); throw; }
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

