百万级 Excel导入数据库 效率太低? 基于 SAX 的事件模型 导入,将会解决 效率问题

简介: 百万级 Excel导入数据库 效率太低? 基于 SAX 的事件模型 导入,将会解决 效率问题

百万级 Excel导入效率太低? 基于 SAX 的事件模型 导入,将会解决 效率问题

如果使用传统的基于 POI 的读写方式,处理大量数据时确实效率较低,可以考虑使用基于 SAX 的事件模型进行读写。

基于 SAX 的事件模型,是一种流式的读写方式,可以直接读取 Excel 文件中的 XML 格式数据,并将其转换为对象模型,因此具有较高的性能和较小的内存占用。

基于 SAX 的事件模型是一种流式的读写方式,它可以直接读取 Excel 文件中的 XML 格式数据,并将其转换为对象模型。在处理大量数据时,该方式具有较高的性能和较小的内存占用。

SAX 是 Simple API for XML(简单 XML 应用程序接口)的缩写,它是一种基于事件的 XML 解析技术,通过注册一些回调函数(事件处理程序),可以实现对 XML 文件的解析。SAX 解析器读取 XML 文档,并发送事件(例如元素开始、元素结束等)给注册的事件处理程序,通过事件处理程序对 XML 文档进行处理。

实现思路:

在基于 SAX 的事件模型中,我们可以通过 XSSFReader 类获取 Excel 文件的输入流,并使用 XMLReader 类来解析 Excel 文件中的 XML 数据。具体步骤如下:

  1. 准备写入的输出流,例如输出到文件或内存中。

2.创建 SAX 事件处理程序,通过实现不同的回调函数来处理不同的事件,例如开始解析 Workbook、解析 Cell 的值、结束解析 Workbook 等。

  1. 获取 Excel 文件输入流,使用 OPCPackage 和 XSSFReader 类来读取 Excel 文件中的 XML 数据。
  2. 获取 Workbook 中每个 Sheet 的 XML 输入流,并使用 XMLReader 类来解析 Excel 文件中的 XML 数据。
  3. 在 SAX 事件处理程序中处理不同的事件,例如开始解析 Workbook、解析 Cell 的值、结束解析 Workbook 等。
  4. 写入缓存的数据,例如每隔一定行数进行一次缓存写入。

需要注意的是,由于使用了 SAX 事件模型,需要自己实现解析事件处理程序。在处理复杂的 Excel 文件时,可能需要编写更为复杂的事件处理程序。同时,使用 SAX 事件模型可以有效减少内存占用,但需要较多的 I/O 操作,因此在处理小规模数据时可能不如基于 POI 的读写方式效率高。

代码示例:

以下是一个基于 SAX 的事件模型示例代码:

// 准备写入的输出流
OutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile));
SXSSFWorkbook writer = new SXSSFWorkbook(new XSSFWorkbook(), 10000);
SXSSFSheet outSheet = writer.createSheet();
// 定义 SAX 事件处理程序
DefaultHandler handler = new DefaultHandler() {
    private boolean isRow = false;
    private int rowIndex = 0;
    private int colIndex = 0;
    private Row outRow = null;
    // 开始解析 Workbook
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if (qName.equals("row")) {
            isRow = true;
            rowIndex++;
            colIndex = 0;
            outRow = outSheet.createRow(rowIndex - 1);
        } else if (qName.equals("c")) {
            String colRef = attributes.getValue("r");
            colIndex = CellReference.convertColStringToIndex(colRef.replaceAll("\\d", ""));
        }
    }
    // 解析 Cell 的值
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (isRow) {
            String cellValue = new String(ch, start, length);
            Cell cell = outRow.createCell(colIndex, CellType.STRING);
            cell.setCellValue(cellValue);
        }
    }
    // 结束解析 Workbook
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName.equals("row")) {
            isRow = false;
            // 每隔 10000 行进行一次缓存写入
            if (rowIndex % 10000 == 0) {
                ((SXSSFSheet) outSheet).flushRows();
            }
        }
    }
};
// 获取 Excel 文件输入流
InputStream is = new BufferedInputStream(new FileInputStream(inputFile));
OPCPackage pkg = OPCPackage.open(is);
XSSFReader reader = new XSSFReader(pkg);
// 获取 Workbook 中每个 Sheet 的 XML 输入流,并解析处理
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(handler);
Iterator<InputStream> sheets = reader.getSheetsData();
while (sheets.hasNext()) {
    InputStream sheetStream = sheets.next();
    InputSource sheetSource = new InputSource(sheetStream);
    parser.parse(sheetSource);
    sheetStream.close();
}
// 写入缓存的数据
writer.write(os);
os.flush();
os.close();
writer.dispose();

上述示例代码通过解析 Excel 文件中的 XML 数据,实现了基于 SAX 的事件模型读写操作。这种方式适用于处理大量数据,具有较高的性能和较小的内存占用。

需要注意的是,由于使用了 SAX 事件模型,需要自己实现解析事件处理程序。在处理复杂的 Excel 文件时,可能需要编写更为复杂的事件处理程序。

注意:

基于 SAX 的事件模型适用于读取基于 XML 格式的 Excel 文件,因此只能读取 XLSX 格式的文件,而不能读取旧版的 XLS 格式。这是因为 XLSX 文件是基于 XML 格式的文件,而 XLS 文件则采用了一种二进制格式,无法通过基于 SAX 的事件模型进行解析。如果需要读取 XLS 文件,可以使用基于 POI 的读写方式,例如 HSSF(适用于读写 XLS 格式文件)和 XSSF(适用于读写 XLSX 格式文件)。

结语

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。

目录
相关文章
|
26天前
|
SQL 缓存 easyexcel
面试官问10W 行级别数据的 Excel 导入如何10秒处理
面试官问10W 行级别数据的 Excel 导入如何10秒处理
53 0
|
3月前
|
关系型数据库 MySQL 数据库连接
python查询数据库的某个表,将结果导出Excel
python查询数据库的某个表,将结果导出Excel
47 0
|
4月前
|
存储 JSON 关系型数据库
Pandas载入txt、csv、Excel、JSON、数据库文件讲解及实战(超详细 附源码)
Pandas载入txt、csv、Excel、JSON、数据库文件讲解及实战(超详细 附源码)
66 0
|
6月前
|
SQL 关系型数据库 数据库
RDS入门——Excel文件转存到RDS数据库实践
本实验将帮助您快速掌握RDS产品的实例开通,熟悉RDS产品的常用功能与基础操作,完成云上数据库搭建。
|
9天前
|
easyexcel 数据库
公司大佬对excel导入、导出的封装,那叫一个秒啊
封装公司统一使用的组件的主要目标是为了简化开发人员的调用流程,避免各个项目组重复集成和编写不规范的代码。文中提到对阿里EasyExcel进行了二次封装,提供了导入和导出功能,并支持模板的导入和导出。此外,还处理了读取数据与实际保存数据不一致的情况,通过提供自定义转换器来解决。
32 0
|
1月前
|
安全 Java 数据库连接
jdbc实现批量给多个表中更新数据(解析Excel表数据插入到数据库中)
jdbc实现批量给多个表中更新数据(解析Excel表数据插入到数据库中)
154 0
|
1月前
|
存储 数据处理 数据格式
Python中导入Excel数据:全面解析与实践
Python中导入Excel数据:全面解析与实践
42 0
|
1月前
|
存储 关系型数据库 MySQL
Python导入Excel数据到MySQL数据库
Python导入Excel数据到MySQL数据库
93 0
|
1月前
|
Java easyexcel 应用服务中间件
【二十五】springboot使用EasyExcel和线程池实现多线程导入Excel数据
【二十五】springboot使用EasyExcel和线程池实现多线程导入Excel数据
214 0
|
1月前
|
SQL Java easyexcel
【Java】百万数据excel导出功能如何实现
【Java】百万数据excel导出功能如何实现
144 0