当前位置: 代码迷 >> 综合 >> 从 SFTP 上下载 80W 数据并解析入库
  详细解决方案

从 SFTP 上下载 80W 数据并解析入库

热度:68   发布时间:2023-12-28 21:59:27.0
  • 需求
  1. 从 SFTP 上下载并解析文本内容为 80W 行的数据并解析入库。
  • 我的实现
  1. 将 80W 数据直接使用 IO 读取到 List 中,然后遍历解析数据,入库。
  • 问题1
  1. 使用 IO 直接将文本数据读取到 List 中,出现内存溢出、gc问题等。
  • 解决方法
  1. 不直接获取 80W 数据,而是批量读取数据,然后解析入库,依次循环着解析入库。
  2. 每次解析 3000 条数据,这样一来,就不会导致内存溢出。
  • 问题2
  1. 成功一批一批的将数据读取出来后,解析时,又出现了问题,因为 for 循环过多,使用 top 查看进程占 CPU 近 300% 多,是吓到我了!!!
  2. 这其中,我预计有 4-5 个 for 循环嵌套,以及 1000 条批量查询 Oracle,1000 条批量插入 Oracle 代码块。
  • 解决方法
  1. 将 for 循环用 Map 替代,这样一来,就不需要 for 循环嵌套着去:去重、比对等操作。直接借助 Map.containsKey 方法就可以判断是否存在。大大提高了效率。
  • 问题3
  1. 使用 jstat -gcutil PID 查看频率(1000ms),发现 S0,S1 堆区并没有回收对象,E 堆区的占用则为 99.99% 一直并未减少。一直这样的话,也会造成堆内存溢出。
  • 解决方法
  1. 将代码中的对象进行清理,我发现代码中有大量的对象在“List”、“Map”中没有清理,所以在每次“集合”使用完毕后,将数据进行 clear 操作;这样操作后,E区 明显得到了优化,“S0,S1”也会在 E堆 达到 100% 时,对 “E堆”中的对象进行清理。
  • 做过的优化
  1. 数据库表索引的创建,会提高至少一倍的搜索效率。最好不用使用“时间”字段加索引并作为条件获取数据,很慢很慢。(极大可能是我SQL问题导致)
  2. 数据库建立“临时表”,这样去重可以直接使用 SQL 将“临时表”与“主表”进行数据去重。
  3. 插入 Oracle 数据时,由每次“1000”减少到每次“500”。
  4. 查询 Oracle 数据时,由每次“1000”减少到每次“500”。
  • 总结
  1. 能用 Map 替代 List ,坚决不用 List;
  2. SQL 能达到最优就必须最优,不管是“索引”,还是函数,都必须上!
  3. 对任何系统外接服务进行操作时,务必不能挑战其极限;比如“Oracle 批量查询,我测得是 1000 条是极限,同事说可以修改配置提示数据量”,但是最好不要 1000 的去获取,这样一来资源全被占用,会导致系统出现问题,严重会导致系统假死。