做质量工作的数据汇总excel技巧(10w 行级别数据的 Excel 导入优
如何优化处理Excel中数十万行数据的导入至数据库操作?
面对数十万级别的Excel数据导入需求,尤其是涉及数据库操作的场景,性能优化显得尤为重要。将详细阐述一个具体案例的优化过程及策略。
项目背景是处理Excel导入的付款记录,数据行数达到数十万级别。实施者需要将数据从Excel模板导入至系统中,涉及数据的读取、校验、转换和存储。在此过程中,数据的导入效率和准确性至关重要。
接下来是具体的优化细节:
一、关于数据读取部分:
最初的手动读取Excel数据并将其存储到List中的方法,在处理大量数据时显得效率低下。优化后的策略是使用EasyPOI工具自动映射Excel行数据到Java对象,减少手动操作,提高代码的可维护性。
二、数据库查询操作的优化:
1. 缓存数据:为了减少数据库查询的IO开销,可以将参与验证的数据缓存到HashMap中。例如,验证房子信息时,可以使用小区、建筑、单元和房号作为键,房子ID作为值存储在HashMap中。这样,后续的验证操作只需在HashMap中进行查找,大大提高了效率。
2. 自定义SessionMapper:Mybatis默认不支持将查询结果直接写入HashMap。为了解决这个问题,可以定制SessionMapper,指定使用MapResultHandler来处理SQL查询的结果集,从而直接将查询结果存储到HashMap中。
会话映射器扩展SqlSessionDaoSupport类
在一个阳光明媚的午后,我们深入了数据库交互的奥秘。今天的主角是我们的会话映射器类,它继承自SqlSessionDaoSupport类,肩负重任,负责数据的映射与交互。让我们一同揭开它的神秘面纱。
当我们谈及数据库中的区域楼宇单元房号与房屋ID之间的映射关系时,这个类显得尤为关键。想象一下,当我们在庞大的数据库中快速查找到特定的房屋信息时,背后就是这个类默默付出的结果。为了设置SqlSessionFactory,我们只需简单地调用setSqlSessionFactory方法,将SqlSessionFactory作为参数传入。
现在让我们关注一个方法:getHouseMapByAreaId。此方法犹如一个智能的导航系统,通过输入区域ID,迅速获取该区域下的房屋映射信息。这个方法巧妙地利用了MapResultHandler处理程序来处理结果集,并将其存储在HashMap中。这个处理程序如同一位数据管家,将查询结果整理得井井有条。
接下来让我们走进MapResultHandler的世界。这个类实现了ResultHandler接口,它的职责是处理查询结果。当查询结果返回时,handleResult方法会被触发,将结果对象存储在mappedResults中。这个HashMap就像一个数据仓库,存储着查询结果的键值对。
再回到我们的Mapper接口。这里有一个名为BaseUnitMapper的接口,其中定义了一个方法getHouseMapByAreaId。这个方法用于查询特定区域的房屋映射信息。在对应的Mapper.xml文件中,我们定义了查询语句和结果映射规则。这些SQL语句如同数据世界的通行证,帮助我们快速获取所需的信息。
只需在代码中使用SessionMapper类对应的方法,即可轻松实现房屋信息的查询。整个过程就像一场流畅的交响乐,各个部分协同工作,为我们提供准确、高效的数据服务。
在开发过程中,我曾使用EasyPOI进行Excel的读写操作。这款工具基于注解的导入导出,修改注解即可修改Excel内容,非常方便,代码维护起来也相对容易。当处理大量Excel数据时,如41万行的数据,EasyPOI在开发环境下可能会出现内存溢出的问题。这时,阿里出品的EasyExcel映入眼帘。它采用和EasyPOI类似的注解方式读写Excel,切换起来十分方便。更重要的是,阿里大神们描述的41万行、25列、45.5m的数据读取,平均耗时仅50秒,对于大Excel文件来说,建议使用EasyExcel进行读取。
让我们深入了解这个工具类的细节:
`public class InsertConsumer {`
` private final static int SIZE = 1000;`
` // 如果需要调整并发数目,只需修改这里的第二个参数`
` static {`
` System.setProperty("java.util.concurrent.ForkJoinPoolmon.parallelism", "4"); }`
` public static void insertData(List list, Consumer consumer, Class ltTgt) {`
` if (list == null || list.size() < 1) { return; }`
` List streamList = new ArrayList();`
` for (int i = 0; i < list.size(); i += SIZE) {`
` int j = Math.min((i + SIZE), list.size());`
` List subList = list.subList(i, j);`
` streamList.add(subList);`
` }`
` // 使用并行流处理数据,注意并发数通常是CPU核心数,不宜随意更改`
` streamList.parallelStream().forEach(consumer); }`
这个类主要利用了Java 8的API,如果你对这些API不熟悉,可以查阅我之前的Java博客。使用方式非常简单,例如:`InsertConsumersertData(feeList, arrearageMapper::insertList);`
Excel作为一种强大的工具,不仅可以用来整理资料、描述数据,还可以进行月度数据及全年汇总,帮助我们更好地理解和分析数据。希望通过这些建议和方法,你能在编程的旅程中更加高效、便捷。