如何拆分foreach/for循环批量向MySQL数据库插入更新数据
可行实现方案
核心分批处理代码
针对你的场景,直接通过数组分块+每批间隔控制即可实现,同时优化了原代码重复调用Split()的性能问题(300万行场景下这部分开销会非常大):
ConnectDB cdb = new ConnectDB(); // 批次大小可根据数据库负载调整,建议初始设为1000~5000 int batchSize = 2000; // 每批处理完的间隔时间(毫秒),避免打满数据库,无压力可设为0 int batchDelayMs = 50; // .NET 6+ 可直接用内置Chunk方法分块 foreach (var batch in arrFinal.Chunk(batchSize)) { foreach (string s in batch) { // 每行只Split一次,避免重复计算 string[] parts = s.Split(';'); if (parts[1] == "REQUEST") { cdb.Insert(parts[0], parts[2], parts[3], parts[4], parts[5], dateLog); } else if (parts[1] == "RESPONSE") { cdb.Update(parts[0], parts[5]); } } // 每批处理完加间隔 Thread.Sleep(batchDelayMs); }
如果是低于.NET 6的版本,没有内置Chunk方法,可以用以下自定义分块逻辑替换:
for (int i = 0; i < arrFinal.Length; i += batchSize) { var batch = arrFinal.Skip(i).Take(batchSize).ToArray(); foreach (string s in batch) { string[] parts = s.Split(';'); if (parts[1] == "REQUEST") { cdb.Insert(parts[0], parts[2], parts[3], parts[4], parts[5], dateLog); } else if (parts[1] == "RESPONSE") { cdb.Update(parts[0], parts[5]); } } Thread.Sleep(batchDelayMs); }
可选优化建议
- 批次大小动态调优:先按初始值运行,观察数据库的CPU、IO、连接数指标,如果负载偏低可以调大批次大小,反之调小,找到最优平衡点
- 增加事务支持:如果你的
ConnectDB类支持事务操作,可以给每批数据开一次事务,处理完成后统一提交,既可以保证数据一致性,还能大幅降低单条操作的事务开销,入库速度能提升几倍 - 分类批量处理:提前把
arrFinal里的REQUEST和RESPONSE类型的数据分开,分别批量处理,同类型操作的数据库执行效率会更高 - 异步改造:如果
Insert和Update有异步实现版本,可以改成异步批量处理,配合await Task.Delay替代Thread.Sleep,降低本地线程资源占用
内容的提问来源于stack exchange,提问作者An3SC
相关产品推荐
相关产品推荐

