使用apache-poi在Java中编写大型Excel,导致CPU使用率较高

unftdfkk  于 2023-01-29  发布在  Java
关注(0)|答案(1)|浏览(472)

写入包含25列的约50万条记录的大型数据。
使用apache-poi流式工作簿将数据从列表写入excel文件。在本地测试时,它也会在本地计算机中产生高CPU峰值。似乎是在将工作簿数据写入文件时造成的

workbook.write(fileOutputStream) // it is causing CPU spikes debugged and confirmed.

它导致云应用程序(部署在Kubernetes)中的CPU使用率较高,并在达到资源限制时重新启动应用程序。我们有一个简单的应用程序,具有2042 Mi内存和1024 m CPU配置。
有没有办法写一个大的excel文件,而不影响CPU和内存和java堆有效。
(NOTE:不能使用csv或其他格式,因为业务要求是excel文件)
代码使用:

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;

import com.king.medicalcollege.model.Medico;

@Service
public class ExcelWriterService {

    // file is an empty file already created
    // Large List around 500K records of medico data [Medico is POJO]

    public File writeData(File file, List<Medico> medicos) {

        SXSSFWorkbook sxssfWorkbook = null;
        try (SXSSFWorkbook workbook = sxssfWorkbook = new SXSSFWorkbook(1);
                FileOutputStream fileOutputStream = new FileOutputStream(file)) {

            Sheet sheet = workbook.createSheet();
            CellStyle cellStyle = workbook.createCellStyle();
            int rowNum = 0;
            for (Medico medico : medicos) {
                Row row = sheet.createRow(rowNum);
                //just adding POJO values (25 fields)  into ROW 
                addDataInRow(medico, row, cellStyle);
                rowNum++;
            }

            //workbook.write causing CPU spike
            workbook.write(fileOutputStream);

            workbook.dispose();

        } catch (Exception exception) {
            return null;
        } finally {
            if (sxssfWorkbook != null) {
                sxssfWorkbook.dispose();
            }
        }

        return file;
    }

    private void addDataInRow(Medico medico, Row row, CellStyle cellStyle) {
        Cell cell_0 = row.createCell(0);
        cell_0.setCellValue(medico.getFirstName());
        cell_0.setCellStyle(cellStyle);
        
        Cell cell_1 = row.createCell(1);
        cell_1.setCellValue(medico.getMiddleName());
        cell_1.setCellStyle(cellStyle);
        
        Cell cell_2 = row.createCell(2);
        cell_2.setCellValue(medico.getLastName());
        cell_2.setCellStyle(cellStyle);
        
        Cell cell_3 = row.createCell(2);
        cell_3.setCellValue(medico.getFirstName());
        cell_3.setCellStyle(cellStyle);
        
        //...... around 25 columns will be added like this
    }
}
cygmwpex

cygmwpex1#

你给SXSSFWorkbook一个窗口大小似乎是正确的(尽管1可能太小而导致问题?)。当行数超过你设置的限制时,工作簿应该被刷新到磁盘,减少内存使用。我怀疑是否有减少cpu使用的解决方案。
您可以尝试通过调整JVM参数来限制内存使用,这样就不会触发K8s限制。x一个月一个月x一个月二个月一个月x一个月三个月一个月x一个月四个月
您是否考虑过使用其他库来编写Excel文件?例如,请看下面的SO答案:Are there any alternatives to using Apache POI Java for Microsoft Office?

相关问题