当前位置:首页 > 科技  > 软件

实现百万级数据从Excel导入到数据库的方式

来源: 责编: 时间:2024-04-09 17:21:06 279观看
导读高手回答场景分析这个案例实际上涉及到多个方面,需要我们系统地分析。让我们首先看看,从Excel中读取百万级数据并将其插入数据库时可能遇到的问题:内存溢出风险加载如此庞大的Excel数据可能导致内存溢出,需要注意内存管理

高手回答

场景分析

这个案例实际上涉及到多个方面,需要我们系统地分析。让我们首先看看,从Excel中读取百万级数据并将其插入数据库时可能遇到的问题:vVG28资讯网——每日最新资讯28at.com

  1. 内存溢出风险

加载如此庞大的Excel数据可能导致内存溢出,需要注意内存管理。vVG28资讯网——每日最新资讯28at.com

  1. 性能瓶颈

处理百万级数据的读取和插入操作可能很耗时,性能优化至关重要。vVG28资讯网——每日最新资讯28at.com

  1. 异常处理策略

读取和导入过程中会有各种潜在问题,我们需妥善处理各类异常情况。vVG28资讯网——每日最新资讯28at.com

内存溢出问题

处理百万级数据,直接加载到内存中显然不现实。解决之道在于采用流式读取,分批处理数据。vVG28资讯网——每日最新资讯28at.com

在技术选型上,选择EasyExcel是明智之举。它专为处理大数据量和复杂Excel文件进行了优化。EasyExcel在解析Excel时,不会将整个文件一次性加载到内存中,而是按行从磁盘逐个读取数据并解析。vVG28资讯网——每日最新资讯28at.com

性能问题

针对百万级数据的处理,单线程显然效率低下。提升性能的关键在于多线程处理。vVG28资讯网——每日最新资讯28at.com

多线程应用涉及两个场景:一是多线程读取文件,另一个是多线程实现数据插入。这涉及到生产者-消费者模式,多线程读取并多线程插入,以最大程度提升整体性能。vVG28资讯网——每日最新资讯28at.com

在数据插入方面,除了利用多线程,还应当结合数据库的批量插入功能以进一步提升速度。vVG28资讯网——每日最新资讯28at.com

错误处理

在文件读取和数据库写入过程中,可能遇到诸多问题,如数据格式错误、不一致性和重复数据等。vVG28资讯网——每日最新资讯28at.com

因此,应分两步处理。首先进行数据检查,在插入操作前检查数据格式等问题,然后在插入过程中处理异常情况。vVG28资讯网——每日最新资讯28at.com

处理方式多种多样,可通过事务回滚或记录日志。一般不推荐直接回滚操作,而是自动重试,若尝试多次仍无效,则记录日志,随后重新插入数据。vVG28资讯网——每日最新资讯28at.com

此外,在这一过程中,需考虑数据重复问题,可在Excel中设定若干字段为数据库唯一约束。遇到数据冲突时,可覆盖、跳过或报错处理。根据实际业务情况选择合适的处理方式,一般情况下,跳过并记录日志是相对合理的选择。vVG28资讯网——每日最新资讯28at.com

解决思路

所以,总体方案如下:vVG28资讯网——每日最新资讯28at.com

利用EasyExcel进行Excel数据读取,因其逐行读取数据而非一次性加载整个文件至内存。为提高并发效率,将百万级数据分布在不同的工作表中,利用线程池和多线程同时读取各个工作表。在读取过程中,借助EasyExcel的ReadListener进行数据处理。vVG28资讯网——每日最新资讯28at.com

在处理过程中,并非每条数据都直接操作数据库,以免对数据库造成过大压力。设定一个批次大小,例如每1000条数据,将从Excel中读取的数据临时存储在内存中(可使用List实现)。每读取1000条数据后,执行数据的批量插入操作,可简单地借助mybatis实现批量插入。vVG28资讯网——每日最新资讯28at.com

此外,在处理过程中,需要考虑并发问题,因此我们将使用线程安全的队列来存储内存中的临时数据,如ConcurrentLinkedQueue。vVG28资讯网——每日最新资讯28at.com

经验证,通过上述方案,读取并插入100万条数据的Excel所需时间约为100秒,不超过2分钟。vVG28资讯网——每日最新资讯28at.com

具体实现

为了提升并发处理能力,我们将百万级数据存储在同一个Excel文件的不同工作表中,然后通过EasyExcel并发地读取这些工作表数据。vVG28资讯网——每日最新资讯28at.com

EasyExcel提供了ReadListener接口,允许在每批数据读取后进行自定义处理。我们可以基于这一功能实现文件的分批读取。vVG28资讯网——每日最新资讯28at.com

pom依赖

首先,需要添加以下依赖:vVG28资讯网——每日最新资讯28at.com

<dependencies>    <!-- EasyExcel -->    <dependency>        <groupId>com.alibaba</groupId>        <artifactId>easyexcel</artifactId>        <version>latest_version</version>    </dependency>    <!-- 数据库连接和线程池 -->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-data-jpa</artifactId>    </dependency></dependencies>

并发读取多个sheet

然后实现并发读取多个sheet的代码:vVG28资讯网——每日最新资讯28at.com

@Servicepublic class ExcelImporterService {    @Autowired    private MyDataService myDataService;        public void doImport() {        // Excel文件的路径        String filePath = "users/paidaxing/workspace/excel/test.xlsx";        // 需要读取的sheet数量        int numberOfSheets = 20;        // 创建一个固定大小的线程池,大小与sheet数量相同        ExecutorService executor = Executors.newFixedThreadPool(numberOfSheets);        // 遍历所有sheets        for (int sheetNo = 0; sheetNo < numberOfSheets; sheetNo++) {            // 在Java lambda表达式中使用的变量需要是final            int finalSheetNo = sheetNo;            // 向线程池提交一个任务            executor.submit(() -> {                // 使用EasyExcel读取指定的sheet                EasyExcel.read(filePath, MyDataModel.class, new MyDataModelListener(myDataService))                         .sheet(finalSheetNo) // 指定sheet号                         .doRead(); // 开始读取操作            });        }        // 启动线程池的关闭序列  executor.shutdown();        // 等待所有任务完成,或者在等待超时前被中断        try {            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);        } catch (InterruptedException e) {            // 如果等待过程中线程被中断,打印异常信息            e.printStackTrace();        }    }}

这段代码通过创建一个固定大小的线程池来并发读取一个包含多个sheets的Excel文件。每个sheet的读取作为一个单独的任务提交给线程池。vVG28资讯网——每日最新资讯28at.com

我们在代码中用了一个MyDataModelListener,这个类是ReadListener的一个实现类。当EasyExcel读取每一行数据时,它会自动调用我们传入的这个ReadListener实例的invoke方法。在这个方法中,我们就可以定义如何处理这些数据。vVG28资讯网——每日最新资讯28at.com

MyDataModelListener还包含doAfterAllAnalysed方法,这个方法在所有数据都读取完毕后被调用。这里可以执行一些清理工作,或处理剩余的数据。vVG28资讯网——每日最新资讯28at.com

ReadListener

接下来,我们来实现这个我们的ReadListener:vVG28资讯网——每日最新资讯28at.com

import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.read.listener.ReadListener;import org.springframework.transaction.annotation.Transactional;import java.util.ArrayList;import java.util.List;// 自定义的ReadListener,用于处理从Excel读取的数据public class MyDataModelListener implements ReadListener<MyDataModel> {    // 设置批量处理的数据大小    private static final int BATCH_SIZE = 1000;    // 用于暂存读取的数据,直到达到批量大小    private List<MyDataModel> batch = new ArrayList<>();        private MyDataService myDataService;    // 构造函数,注入MyBatis的Mapper    public MyDataModelListener(MyDataService myDataService) {        this.myDataService = myDataService;    }    // 每读取一行数据都会调用此方法    @Override    public void invoke(MyDataModel data, AnalysisContext context) {        //检查数据的合法性及有效性        if (validateData(data)) {            //有效数据添加到list中            batch.add(data);        } else {            // 处理无效数据,例如记录日志或跳过        }                // 当达到批量大小时,处理这批数据        if (batch.size() >= BATCH_SIZE) {            processBatch();        }    }        private boolean validateData(MyDataModel data) {        // 调用mapper方法来检查数据库中是否已存在该数据        int count = myDataService.countByColumn1(data.getColumn1());        // 如果count为0,表示数据不存在,返回true;否则返回false        if(count == 0){         return true;        }                // 在这里实现数据验证逻辑        return false;    }    // 所有数据读取完成后调用此方法    @Override    public void doAfterAllAnalysed(AnalysisContext context) {        // 如果还有未处理的数据,进行处理        if (!batch.isEmpty()) {            processBatch();        }    }    // 处理一批数据的方法    private void processBatch() {        int retryCount = 0;        // 重试逻辑        while (retryCount < 3) {            try {                // 尝试批量插入                myDataService.batchInsert(batch);                // 清空批量数据,以便下一次批量处理                batch.clear();                break;            } catch (Exception e) {                // 重试计数增加                retryCount++;                // 如果重试3次都失败,记录错误日志                if (retryCount >= 3) {                    logError(e, batch);                }}

通过自定义MyDataModelListener,在读取Excel文件过程中可实现数据处理。每读取一条数据后,将其加入列表,在列表累积达到1000条时,执行一次数据库批量插入操作。若插入失败,则进行重试;若多次尝试仍失败,则记录错误日志。vVG28资讯网——每日最新资讯28at.com

批量插入

这里批量插入,用到了MyBatis的批量插入,代码实现如下:vVG28资讯网——每日最新资讯28at.com

import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapperpublic interface MyDataMapper {    void batchInsert(List<MyDataModel> dataList);    int countByColumn1(String column1);}

mapper.xml文件:vVG28资讯网——每日最新资讯28at.com

<insert id="batchInsert" parameterType="list">    INSERT INTO paidaxing_test_table_name (column1, column2, ...)    VALUES     <foreach collection="list" item="item" index="index" separator=",">        (#{item.column1}, #{item.column2}, ...)    </foreach></insert><select id="countByColumn1" resultType="int">    SELECT COUNT(*) FROM your_table WHERE column1 = #{column1}</select>


vVG28资讯网——每日最新资讯28at.com


vVG28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-82361-0.html实现百万级数据从Excel导入到数据库的方式

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 您必须了解的 21 个 HTML 技巧

下一篇: Rust命名规范的最佳实践,你学会了吗?

标签:
  • 热门焦点
  • 直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    旗舰机基本上使用的都是双曲面屏幕,这就让很多喜欢直屏的爱好者在苦等一款直屏旗舰,这次,你们等到了。据博主数码闲聊站带来的最新爆料称,Redmi下代旗舰K70 Pro和iQOO 12两款手
  • 如何正确使用:Has和:Nth-Last-Child

    我们可以用CSS检查,以了解一组元素的数量是否小于或等于一个数字。例如,一个拥有三个或更多子项的grid。你可能会想,为什么需要这样做呢?在某些情况下,一个组件或一个布局可能会
  • 只需五步,使用start.spring.io快速入门Spring编程

    步骤1打开https://start.spring.io/,按照屏幕截图中的内容创建项目,添加 Spring Web 依赖项,并单击“生成”按钮下载 .zip 文件,为下一步做准备。请在进入步骤2之前进行解压。图
  • 虚拟键盘 API 的妙用

    你是否在遇到过这样的问题:移动设备上有一个固定元素,当激活虚拟键盘时,该元素被隐藏在了键盘下方?多年来,这一直是 Web 上的默认行为,在本文中,我们将探讨这个问题、为什么会发生
  • Python异步IO编程的进程/线程通信实现

    这篇文章再讲3种方式,同时讲4中进程间通信的方式一、 Python 中线程间通信的实现方式共享变量共享变量是多个线程可以共同访问的变量。在Python中,可以使用threading模块中的L
  • 苹果、三星、惠普等暂停向印度出口笔记本和平板电脑

    集微网消息,据彭博社报道,在8月3日印度突然禁止在没有许可证的情况下向印度进口电脑/平板及显示器等产品后,苹果、三星电子和惠普等大公司暂停向印度
  • 苹果公司要求三星和LG Display生产「无边框」OLED iPhone显示屏

    据 The Elec 报道,苹果已要求其供应商为未来的 iPhone 型号开发「无边框」OLED 显示面板。苹果显然已要求三星和 LG Display 开发新的 OLED 显示面
  • 英特尔Xe-HP项目终止,将专注Xe-HPC/HPG系列显卡

    据10 月 31 日消息报道,英特尔高级副总裁兼加速计算系统和图形事业部总经理 表示,Xe-HP“ Arctic Sound” 系列服务器 GPU 已经应用于 oneAPI devcloud 云服
  • 利用职权私自解除被封帐号 Meta开除20多名员工

    11月18日消息,据外媒援引知情人士表示,过去一年时间内,Facebook母公司Meta解雇或处罚了20多名员工以及合同工,指控这些人通过内部系统以不当方式重置用户帐号,其
Top