• 100000行级别数据的 Excel 导入优化


    需求说明

    项目中有一个 Excel 导入的需求:缴费记录导入由实施 / 用户 将别的系统的数据填入我们系统中的 Excel 模板,应用将文件内容读取、校对、转换之后产生欠费数据、票据、票据详情并存储到数据库中。

    在接手之前可能由于之前导入的数据量并不多没有对效率有过高的追求。但是到了 4.0 版本,预估导入时Excel 行数会是 10w+ 级别,而往数据库插入的数据量是大于 3n 的,也就是说 10w 行的 Excel,则至少向数据库插入 30w 行数据。因此优化原来的导入代码是势在必行的。逐步分析和优化了导入的代码,使之在百秒内完成(最终性能瓶颈在数据库的处理速度上,测试服务器 4g 内存不仅放了数据库,还放了很多微服务应用。处理能力不太行)。具体的过程如下,每一步都有列出影响性能的问题和解决的办法。

    迭代记录

    1. 第一版:POI + 逐行查询校对 + 逐行插入

    这个版本是最古老的版本,采用原生 POI,手动将 Excel 中的行映射成 ArrayList 对象,然后存储到 List,代码执行的步骤如下:
     
    1、手动读取 Excel 成 List
     
    2、循环遍历,在循环中进行以下步骤
     
    3、检验字段长度
    一些查询数据库的校验,比如校验当前行欠费对应的房屋是否在系统中存在,需要查询房屋表
    写入当前行数据
     
    4、返回执行结果,如果出错 / 校验不合格。则返回提示信息并回滚数据
     
    显而易见的,这样实现一定是赶工赶出来的,后续可能用的少也没有察觉到性能问题,但是它最多适用于个位数/十位数级别的数据。存在以下明显的问题:查询数据库的校验对每一行数据都要查询一次数据库,应用访问数据库来回的网络IO次数被放大了 n 倍,时间也就放大了 n 倍写入数据也是逐行写入的,问题和上面的一样数据读取使用原生 POI,代码十分冗余,可维护性差。
     

    2. 第二版:EasyPOI + 缓存数据库查询操作 + 批量插入

    针对第一版分析的三个问题,分别采用以下三个方法优化

    缓存数据,以空间换时间

    逐行查询数据库校验的时间成本主要在来回的网络IO中,优化方法也很简单。将参加校验的数据全部缓存到 HashMap 中。直接到 HashMap 去命中。

    自定义 SessionMapper

    Mybatis 原生是不支持将查询到的结果直接写人一个 HashMap 中的,需要自定义 Sessio

  • 相关阅读:
    SpringBoot快速初始化
    【java_wxid项目】【第八章】【Apache ShardingSphere集成】
    14:00面试,14:06就出来了,问的问题过于变态了。。。
    网络安全(黑客)自学
    Python进阶之迭代器
    第15届蓝桥STEMA测评真题剖析-2023年10月29日Scratch编程初中级组
    信息系统项目管理师---第十七章 战略管理 第十八章 组织级项目管理 第十九章 流程管理
    XA分布式事务处理
    【Java集合框架】21 ——LinkedHashMap 类
    Exam diagnosis Privacy Policy
  • 原文地址:https://blog.csdn.net/m0_53914150/article/details/128167540