千万数量级excel,如何快速导入?
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
前言最近星球中有两位小伙伴问了我关于excel数据导入的问题:
今天就跟大家一起聊聊,千万级excel数据导入功能该如何实现,希望这篇文章对你会有所帮助。 1. 问题对于千万级excel数据导入功能,可能会遇到一些问题,我们先聊聊会到哪些问题。 1.1 单个Sheet存不了我们都知道excel的一个Sheet,对于2003版,最大行数是65536行,对于2007以上版本,最大行数是1048576行。 由此可见,千万级的数据是没法保存到excel的单个Sheet当中的。 那我们该怎么办呢? 1.2 出现OOM问题即使我们想办法,把一千万的数据保存到excel当中了,但如果程序在导入数据时,将这些数据加载到内存中,内存会直接爆掉,出现OOM问题。 我们又该怎么办呢? 1.3 导入耗时太长如果你在程序中使用单个线程,在循环中一个个将excel的数据写入到数据库,会有大量的远程IO操作,极有可能会导致该excel程序导入耗时很长。 如何优化excel的导入性能呢? 1.4 丢数据了如果excel中有1000万的数据,但是你导入数据的数据只有995万,少了5万数据。 如何快速查询哪些数据导入失败了呢? 如何处理异常数据呢? 1.5 CPU使用率过高如果我们将excel改成多线程导入,并且每个线程导入时间非常短,可能会导致线程之间在不停的 这时又该怎么办呢? 带着这些问题,开始今天的文章之旅。 2. EasyExcel导入海量数据的Excel文件,最大的问题莫过于程序出现OOM了。 一旦出现OOM,程序将会直接挂掉。 为了防止出现OOM问题,建议使用阿里开源的excel导入导出工具: EasyExcel采用 例如下面这段代码: 在上面的这段代码中,DATA_SIZE为100000,即每读取100000条数据,就会调用一次MySheetListener的invoke()方法,并将数据加入到dataList中,最终通过saveData()方法进行批量保存。 这样可以避免一次性将全部数据读取到内存中,降低内存使用的风险。 对于百万以内的数据,放在excel的一个 但如果有千万级的数据,放在一个Sheet显然是保存不下的,我们可以将数据保存到多个Sheet中,或者直接将数据保存
3. 性能问题通过前面使用EasyExcel能够保证读取excel,不会出现OOM问题。 但可能会出现性能问题。 那么该如何解决呢? 3.1 批量保存数据我们的程序在读取到一批excel数据之后,可能会有些业务逻辑处理,然后将数据保存到数据库当中。 你可以在一个循环中,每一条数据进行一次业务逻辑处理,然后保存数据。 例如这样的: 如果是这样保存数据,性能可能会大打折扣,因为上面的这段代码,在for循环中一次只保存一条数据,每次都需要访问远程的数据库,影响数据写入的性能。 优化如下: 每次对数据库操作都是批量操作,这样可以减少访问数据库的频率,从而可以显著的提升写入数据的性能。 但需要注意的是:批量写入数据时,一次性也不要写入太多的数据。比如如果一次性写入10万的数据,可能会导致写入数据库超时,或者访问该数据库的其他程序出现异常。 如果数据太多了,可以分配写入数据库。 例如: 我们可以通过Lists.partition方法将大数据saveList进行分割,每1000条记录为一组。
3.2 多线程通过上面批量保存数据的优化,将数据的写入数据库的性能提升了一些。 但如果程序除了保存数据之外,还有一些业务逻辑,这样优化还是不够的。 如果你的程序用的是单线程,并且在一个循环中一条数据一条数据去处理业务逻辑,显然效率有点低。 你可以将代码优化成批量处理业务逻辑,但有的时候,单个处理逻辑非常复杂,改成批量处理改造成本非常大。 这时该如何优化性能呢? 答:使用多线程。 我们可以使用 例如: 最后将批量保存数据的地方改成resultList的批量保存。 其中executor是配置的线程池,注意我们在日常工作中,使用CompletableFuture的场景中,记得要配置线程池,否则每次都是new一个新的线程。 此外,如果使用多线程处理业务,可能会导致CPU使用率过高,要控制线程的数量,不能配置太多。 但线程数也不能配置太少,会影响业务处理的速度,最后可以做成配置项,可以根据项目的实际情况进行动态调整。 3.3 原始JDBC为了方便对数据库进行操作,少写一些访问数据库的代码,通常情况下,我们在项目中会使用一些开源的ORM映射框架,比如:Mybatis或者Hibernate等。 这些ORM映射框架,虽说确实可以帮我们提升开发效率。 但它们也引入了额外的逻辑,提升了代码的复杂度,比如底层使用了反射机制,相对于直接new一个对象,它的效率更低。 使用原生JDBC进行数据库操作,确实需要多写一些代码,比如获取数据库Connection、获取PreparedStatement等。 例如: 但这样的批量操作效率却非常高。 4. 异常处理在数据导入的过程中,可能会出现一些异常情况,比如:网络抖动,导致某一次写入数据失败了。 这时该如何处理呢? 答:增加 我们在批量保存数据时,可以把异常捕获一下,如果判断是数据库的某些异常,可以自动重试2次,如果有任意一次成功了,则直接返回成功,否则返回失败。 在日志中打印一条异常日志,记录批次编号,集合的第一个元素和最后一个元素的数据,方便后面可以快速定位数据。 导入成功之后,一定要检查excel中的数据总条数,跟数据库中导入成功的数据总条数是否相等。 看看有没有漏数据的情况。 对于重试之后还是没有导入成功的数据,我们可以通过日志搜索出来,分析失败的原因,是程序bug,还是数据问题。 如果是程序bug,修复了bug之后重新导入数据。 如果是数据问题,要咨询相关业务人员,是直接丢弃数据,还是修改excel重新导入。当然这时的excel不是完整的excel,而是只包含异常数据的excel。 5.数据重复我们的程序在导入excel文件时,通常情况下,需要先检查一下,该excel中是否存在重复的数据。 但如果excel数据太多,没办法一次加载到内存,根本没法校验整个excel的数据的重复性,这时该怎么办呢? 我们可以校验每一批次的数据中,是否包含了重复的数据,如果有重复的数据,则直接忽略,不用写入数据库。 防止数据库中出现重复数据最有效的办法是,在表中给关键字段增加 这时如果我们的程序在并发批量插入数据时,刚好插入了重复的数据,就会报:Duplicate entry * for key,导致程序导入失败。 其实在导入数据时,可以使用 这样及时excel文件不小了导入了两次,产生了并发写入的问题,也不会对程序造成太大的影响。 阅读原文:点击这里 该文章在 2026/8/6 15:20:56 编辑过 |
关键字查询
相关文章
正在查询... |