不同方式通過POI讀取xlsx文件後由Mybatis向MySQL寫入30萬條數據性能分析

情景:有一個一條記錄有20個字段,共30萬條記錄的xlsx文件,文件大小大約30兆,需要將其內容讀取後寫入數據庫。

這意味着需要向數據庫寫入30萬條數據,讀取xlsx方面,用的是POI,用了幾種方式做,性能對比如下:

一、MyBatis的xml裏逐條寫入:一條記錄生成一條SQL語句並執行一次,這種做法性能過低,不作討論。

二、MyBatis的xml裏用foreach方式,一次寫入2000條數據

1.POI:XSSFWorkbook讀xlsx:

List<List<Object>> result = new ArrayList<>();
		Workbook wb = new XSSFWorkbook(new File(filePath));
		for (Sheet sheet : wb) {
			for (Row row : sheet) {
				List<Object> rowData = getRowData(row);
				result.add(rowData);
			}
		}
		wb.close();
		return result;

   這種方式在xlsx內有30萬條數據的情況下報錯。

    2.POI:SAX模式讀xlsx:

File xlsxFile = new File(filePath);
		OPCPackage p = OPCPackage.open(xlsxFile.getPath(), PackageAccess.READ);
		Xlsx2ListData xlsx2ListData = new Xlsx2ListData(p, minColumns, null);
		List<List<Object>> result = xlsx2ListData.process();
		p.close();
		return result;

使用該方法一次讀取30萬條數據,形成一個size=30萬的list,然後每次寫入2000條數據,耗時1320s。

3.POI:SAX方式讀取xlsx文件,讀取每一行調用RowDataProcesser:

File xlsxFile = new File(filePath);
		OPCPackage p = OPCPackage.open(xlsxFile.getPath(), PackageAccess.READ);
		Xlsx2ListData xlsx2ListData = new Xlsx2ListData(p, minColumns,
				rowDataProcesser);
		xlsx2ListData.process();
		p.close();

該方式使用RowDataProcesser接口,讀取一行就寫入list,list滿後向數據庫批量寫入,同樣的機器,同樣的數據,耗時1356s

第二,第三種方式讀取xlsx文件分別耗時:13s,12s也就是說,數據庫IO佔了大部分時間。

結論:SAX模式讀取大文件(30萬條數據)向數據庫寫入的情景下,SAX模式的兩種讀取方式性能差距不大,真正的性能瓶頸是數據庫I/O,針對這個問題,嘗試增大list容量,減少數據庫IO次數。

將list容量增大至1萬,即每次向數據庫寫入1萬條數據。

結果報錯了:PacketTooBigException

目前還沒有找到更快的方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章