【问题标题】:Performance : Writing oracle ResultSet into XLSX using Java, Apache-POI性能:使用 Java、Apache-POI 将 oracle ResultSet 写入 XLSX
【发布时间】:2015-04-23 10:10:39
【问题描述】:

我需要使用 Apache POI 将 600-700k 记录写入 xlsx 文件。 我目前使用的代码是:

public void writeRecords(ResultSet rs)  {
             try{

            SXSSFWorkbook wb = new SXSSFWorkbook();  
            wb.setCompressTempFiles(true);

            SXSSFSheet sh = (SXSSFSheet)wb.createSheet("Sheet 1");
            Row row = null;


            int numColumns = rs.getMetaData().getColumnCount();

               //   Workbook wb = ExcelFileUtil.createExcelWorkBook(true, 5);


                sh.setRandomAccessWindowSize(100);// keep 100 rows in memory, exceeding rows will be flushed to disk
               Row heading = sh.createRow(1);

                ResultSetMetaData rsmd = rs.getMetaData();

                for(int x = 0; x < numColumns; x++) {
                    Cell cell = heading.createCell(x+1);
                    cell.setCellValue(rsmd.getColumnLabel(x+1));
                }

                int rowNumber = 2;
                int sheetNumber = 0;

                while(rs.next()) {

                    row = sh.createRow(rowNumber);
                    for(int y = 0; y < numColumns; y++) {
                        row.createCell(y+1).setCellValue(rs.getString(y+1));
                      //  wb.write(bos);
                    }

                    rowNumber++;
                }

                FileOutputStream out = new FileOutputStream("C:/Users/test1.xlsx");
                wb.write(out);
                out.close();
             }
                catch (Exception e){
                    e.printStackTrace();

                }

它运行良好,但写入约 65k 条记录需要约 50 分钟。 在 5-6 分钟内获取了 65k 条记录的结果集。

有什么方法可以在大约 10-15 分钟内写出 600,000-700,000 条记录 使用 POI。 我们将无法将数据导出为 CSV 格式,因为最终用户已设置为仅导入 xlsx 文件。 问候, 图沙尔

【问题讨论】:

  • 你怎么知道 ResultSet 是在 7 秒内获取的?在上面的代码中,您在写入行时仍在获取。
  • 另外,当您向其中扔一个包含 700k 行的电子表格时,Excel 的行为如何?那个文件有多大?
  • 我在前后记录了时间戳:ps = con.prepareStatement("select * from table_1 where rownum
  • executeQuery 不包括获取数据。当您致电 next() 时会发生这种情况
  • SXSSFWorkbook 的默认窗口大小为 100。您应该将此值与 rs.next() 获取的行数相匹配,正如 Cristobal 在他的回答中提到的那样,以提高总时间,因为 GC 可能能够在获取数据时清理行。

标签: java oracle apache-poi resultset xlsx


【解决方案1】:

检查 PreparedStatement 的 fetchSize。如果不显式设置,该值可能与实际表相比非常小,对中大量数据的查询速度会受到非常影响。

Check this question 了解更多信息。

另外,考虑是否有必要使用setCompressTempFilesSXSSFWorkbook。如果需要,保留在内存中的行的值将直接影响性能。

【讨论】:

    【解决方案2】:

    如果你能写文件输出形式 sqlplus 会非常快。

    创建文件如下 mycsv.sql:

       SET DEFINE OFF
       SET ECHO OFF
       SET SERVEROUTPUT OFF
       SET TERMOUT OFF
       SET VERIFY OFF
       SET FEEDBACK OFF
       SET PAGESIZE 10000
       SET ARRAYSIZE 5000
       REM SET HEAD OFF
       SET LINE 500
       spool /tmp/mycsvfile.csv;
       select * from MY_table;
       spool off;
       exit;
    

    在 Linux 提示符下,您可以像

    一样运行
    $> sqlplus username/password @/tmp/mycsv.sql
    

    【讨论】:

    • 根本不回答问题。
    • 您好,我的意思是,您的最终目标是将输出写入文件,然后使用 sqlplus。使用 sqlplus 会更快
    • 嗨。我的意思是,如果您的最终目标是将 csv 输出写入文件,则使用 sqlplus。 1.在sqlplus中做会更快。 2.如果Apache中的数据非常高,你可能会出现内存不足的错误。 3. 从 DB 获取数据到 Apache 并写入文件,我是说删除中间 Apache 层,这将是一个很好的优势。我希望这很清楚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    相关资源
    最近更新 更多