最近项目上,使用了传统的导入方式,用 excel 驱动 将数据放入临时表中,再通过循环一条条将数据经过一系列的验证,最后再将数据插入表中。
本来我们的项目是内部使用的业务系统,是没有什么大问题的,但最近接入的项目确是有着几十上百万数据的系统,这也就意味着,原来那一套已经无法满足使用需求了。
这不项目上使用时,连连暴雷,说是导入数据超时,一度导致系统无法使用,既然问题出现了,那我们只能想办法来解决问题了。
对于我们这种对项目非常熟悉的程序员来说,我几乎一眼就看出了系统的瓶颈所在,真正慢就是因为每条数据,都是有这样一个过程。
单独开数据库连接,一系列的验证,查数据库,最后还要插入有触发器的临时表时表里边,就这样一套逻辑下来,一条记录都要几十秒的时间,这样能不超时的吗?
那既然知道了问题的所在,我们就要给出解决方案了,这无非就是解决将速度提升,下边的几条建议,大家可以参考下:
- 数据库性能:
- 检查数据库查询的效率。使用数据库查询分析器或其他工具来评估查询性能。
- 确保数据库索引正确设置,以加快查询速度。
- 代码优化:
- 检查代码中是否有性能低下的循环、递归或其他低效操作。
- 避免在循环中频繁地进行数据库操作。
- 并行处理:
- 如果导入过程中有大量的数据处理步骤,考虑使用并行处理或异步编程来提高性能。
- 网络延迟:
- 如果数据是通过网络导入的,检查网络延迟或带宽问题。
- 服务器资源:
- 检查服务器的CPU、内存和磁盘使用率。如果资源使用率过高,可能会影响导入速度。
- 考虑升级服务器硬件或优化服务器配置。
- 日志和调试:
- 查看应用程序的日志文件,检查是否有任何错误或异常。
- 使用调试工具来跟踪导入过程中的性能瓶颈。
- 批量导入:
- 如果可能的话,考虑使用数据库的批量导入功能,而不是单条记录插入,以提高导入速度。
- 优化数据格式:
- 确保导入的数据格式是最优化的,例如使用二进制格式而不是文本格式。
- 外部服务调用:
- 如果导入过程中涉及外部服务调用,检查这些服务的响应时间和可用性。
一般说来,大家看到这些理论知识,也是只是大概有方向而已,具体如何解决,这还得看你是不是个有经验的开发者。
接下来,我就分享下我对本项目的经验,主要采用了批量导入这些建议,来解决导入速度,因为本次项目是用 sqlserver 数据库,接下来,我们会用到这些sqlserver 专用类库来解决问题。
- 导入excel 这个是不会变的,拿数据其实是不慢的,真正慢的是处理每条数据的循环。
- 这里我们用了一个中转的临时表,就是你需要验证数据,我们把所有数据存入表中,只拿符合要求的数据,导入我们的系统,最后不符合要求的,再一并提示通知用户,这样就避免了单条提示跟检查浪费的时间。
- 那这里大家可能会有疑问,插入表的时候,不是很慢吗?更何况是几十万上百万的数据,那这里就会用到接下来的sqlserver 的一个快速导入的类库。
- using (SqlBulkCopy copy = new SqlBulkCopy(connectionString))
{
try
{
copy.DestinationTableName = "temptable";
copy.BatchSize = dt.Rows.Count;
copy.ColumnMappings.Add("a", "a");
copy.ColumnMappings.Add("b", "b");
copy.ColumnMappings.Add("c", "c");
copy.ColumnMappings.Add("d", "d");
copy.ColumnMappings.Add("e", "e");
copy.ColumnMappings.Add("f", "f");
copy.ColumnMappings.Add("g", "g");
copy.ColumnMappings.Add("h", "h");
copy.ColumnMappings.Add("i", "i");
copy.ColumnMappings.Add("j", "j");
copy.ColumnMappings.Add("k", "k");
copy.ColumnMappings.Add("l", "l");
copy.ColumnMappings.Add("m", "m");
copy.WriteToServer(dt);
}
catch (Exception exception)
{
Logger.Error(exception.ToString());
return false;
}
} - 使用以上语句几百W条数据,都可以在几秒内进入表中,这样就省下不少时间了。以上的表可以自己命名,字段自己定义,这样就省下了检查的时间。
- 我们通过sql把符合要求的表数据拿出来,插入表中。
- 这里我们就只开一次连接,写一句 insert into select 这样的语句,只需要一句sql,就将我们的表里边的数据,直接插入我们的业务表里边的。这里实验了一下,速度确实是相当快的,哪怕是插入的表,有触发器这样的语法存在,我们还是很快的处理完数据。
- 到此为止,我们的优化过程就处理完毕了,这里就分享一些经验给大家,毕竟,只看理论知识,大家没经验的话,解决问题,还是可能有点不知道如何入手。提供一个思路,一些实践,大家可以更好,更快的解决问题。
以上是自己的做为资深开发的一些个人经历,把这些经验分享给大家,希望以后大家在从事开发中,可以避免不必要的麻烦,跟浪费时间精力。
要是大家喜欢我的文章的话,可以在文章下留言或是联系我,共同进步,共同探讨开发的一些案例,促进彼此间的交流,分享一些日常的开发趣事。
- THE END -
最后修改:2024年4月12日
共有 0 条评论