JAva poiを使用してexcelをエクスポートするのは遅すぎます
シーンはデータをクエリーしてexcelをエクスポートし、インタフェースの応答が遅すぎます.
処理インタフェースが遅いので、まずどの部分が遅いかを見つけなければなりません.
ログを打って各段階を見て時間を費やして、10 W本のデータは関連してsqlを検索して費用を使います 3 s,excelのエクスポートには5 Sかかり,応答伝送時間はすぐに重要な問題ではない.
ネット上でexcelフレームワークをエクスポートするのは、easyExcel(アリババ、メモリ消費量が小さい)、easyPoi(APIが豊富)、POI、jacobなどがたくさんあります.同じように見る.
1.EasyPoi
EasyPoiフレームワークの大きなファイルAPIをエクスポートするのは、メモリのオーバーフローを防ぐためで、もともとデータファイルがメモリにロードされていたため、同時に大きなファイルをエクスポートするとメモリがオーバーフローしやすいため、一時的なデータがディスクに書き込まれてこの問題を防ぐためで、EasyExcelは生まれながらにしてそれをしています.
しかし、インタフェースの応答速度を速めることを目的としています.
EasyExcel:https://alibaba-easyexcel.github.io/quickstart/fill.html#%E6%95%B0%E6%8D%AE%E9%87%8F%E5%A4%A7%E7%9A%84%E5%A4%8D%E6%9D%82%E5%A1%AB%E5%85%85
EasyPoi:https://opensource.afterturn.cn/doc/easypoi.html#8
2.EasyExcel
その後、easyexcelを利用してsheetをページングしてエクスポートする方法、例えば10 Wのデータ、1 Wを1つのsheetページにエクスポートし、EasyExcelを利用してこれを行うことができます.次のようになります.https://www.cnblogs.com/ningJJ/p/11435465.html
しかし、この方法は試験されたが、実際には各sheet間は依然としてシリアルであり、インタフェースの速度を速めることはできない.
マルチスレッドで各sheetを同時エクスポートしようとしましたが失敗しました.poiは単一ファイルのマルチsheet書き込みにマルチスレッドをサポートしていません.同じsheetに繰り返し書き、プログラムが間違っています.
3.JACOB
JACOBもあり、 JAVA-COM Bridgeの略で、(自動化されたcomアクセス機能を提供し、JNI機能によってwindowsプラットフォーム下のcomコンポーネントまたはwin 32システムライブラリにアクセスするものでもある).これはCを利用してofficeの操作を完成して、前にそれを使ってPPTを画像にトランスコードしたことがあって、とても速くて、しかしwindowsの上で運行することしかできなくて、速いですが需要を満たしません.
4.HuTool
HutoolツールクラスにはBigExcelWriterもあり、大きなファイルの書き出しに使用されますが、メモリオーバーフローの問題のみが解決されます.
ZIPUtil、ファイルを圧縮して、私たちの問題は書いていて、データの伝送ではありませんので、役に立たないです.
5.CSV
最後に、ファイルをCSV形式にエクスポートする最も速い方法があることがわかりました.
実はPOIは各セルに対して书くので、スタイルのフォントの幅などを含んで、IOのタスクが重いだけではなくて、计算のタスクも重いです、csvならば、直接テキストの书くので、実は直接Printerの流れで1行1行の文字を书くので、とても速くて、しかし欠点はプログラムの中でセルのスタイルの调整を行うことができません. EasyPOIにCSVのAPIがありましたが、私は実験に失敗し、最後に使用したアパッチのCommoms-csv. 以前の関連5テーブルクエリーsqlは、3 sから2 s. に変更され、データベースに複数回アクセスする単一テーブルクエリーに変更された.また、csvをエクスポートする場合は、符号化をGBKに設定しなければならない.そうしないと、excelで開くと中国語が文字化けしてしまう(ただし、このように他のソフトウェアで開くと文字化けして、先に放っておく).ネット上にはファイルの一番前にいくつかのバイトをbomとして書き込み、excelソフトウェアでファイルを識別する符号化方式がutf-8になったが、私はこの方式を試験して失敗した.https://www.iteye.com/blog/rainbow702-1426354
処理インタフェースが遅いので、まずどの部分が遅いかを見つけなければなりません.
ログを打って各段階を見て時間を費やして、10 W本のデータは関連してsqlを検索して費用を使います 3 s,excelのエクスポートには5 Sかかり,応答伝送時間はすぐに重要な問題ではない.
ネット上でexcelフレームワークをエクスポートするのは、easyExcel(アリババ、メモリ消費量が小さい)、easyPoi(APIが豊富)、POI、jacobなどがたくさんあります.同じように見る.
1.EasyPoi
EasyPoiフレームワークの大きなファイルAPIをエクスポートするのは、メモリのオーバーフローを防ぐためで、もともとデータファイルがメモリにロードされていたため、同時に大きなファイルをエクスポートするとメモリがオーバーフローしやすいため、一時的なデータがディスクに書き込まれてこの問題を防ぐためで、EasyExcelは生まれながらにしてそれをしています.
しかし、インタフェースの応答速度を速めることを目的としています.
EasyExcel:https://alibaba-easyexcel.github.io/quickstart/fill.html#%E6%95%B0%E6%8D%AE%E9%87%8F%E5%A4%A7%E7%9A%84%E5%A4%8D%E6%9D%82%E5%A1%AB%E5%85%85
EasyPoi:https://opensource.afterturn.cn/doc/easypoi.html#8
2.EasyExcel
その後、easyexcelを利用してsheetをページングしてエクスポートする方法、例えば10 Wのデータ、1 Wを1つのsheetページにエクスポートし、EasyExcelを利用してこれを行うことができます.次のようになります.https://www.cnblogs.com/ningJJ/p/11435465.html
しかし、この方法は試験されたが、実際には各sheet間は依然としてシリアルであり、インタフェースの速度を速めることはできない.
マルチスレッドで各sheetを同時エクスポートしようとしましたが失敗しました.poiは単一ファイルのマルチsheet書き込みにマルチスレッドをサポートしていません.同じsheetに繰り返し書き、プログラムが間違っています.
3.JACOB
JACOBもあり、 JAVA-COM Bridgeの略で、(自動化されたcomアクセス機能を提供し、JNI機能によってwindowsプラットフォーム下のcomコンポーネントまたはwin 32システムライブラリにアクセスするものでもある).これはCを利用してofficeの操作を完成して、前にそれを使ってPPTを画像にトランスコードしたことがあって、とても速くて、しかしwindowsの上で運行することしかできなくて、速いですが需要を満たしません.
4.HuTool
HutoolツールクラスにはBigExcelWriterもあり、大きなファイルの書き出しに使用されますが、メモリオーバーフローの問題のみが解決されます.
ZIPUtil、ファイルを圧縮して、私たちの問題は書いていて、データの伝送ではありませんので、役に立たないです.
5.CSV
最後に、ファイルをCSV形式にエクスポートする最も速い方法があることがわかりました.
実はPOIは各セルに対して书くので、スタイルのフォントの幅などを含んで、IOのタスクが重いだけではなくて、计算のタスクも重いです、csvならば、直接テキストの书くので、実は直接Printerの流れで1行1行の文字を书くので、とても速くて、しかし欠点はプログラムの中でセルのスタイルの调整を行うことができません.
public void logDownload(@RequestBody LogExportParam param, HttpServletResponse response) throws IOException, InterruptedException {
response.setContentType("application/csv");
response.setCharacterEncoding("gbk");
String fileName = "log" + System.currentTimeMillis() + ".csv";
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
// ,
String encoding = "GBK";
Writer outputStreamWriter = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), encoding));
CSVFormat csvFormat = CSVFormat.DEFAULT.withHeader(" ", " ", " ", " ", " ", " ", " ", " ");
CSVPrinter csvPrinter = new CSVPrinter(outputStreamWriter, csvFormat);
logger.info(" " + new Date().getMinutes() + "n" + new Date().getSeconds() + "s");
List classroomList = classroomInfoService.classroomList(param.getSchoolId(), param.getTeachingBuildingId(), param.getClassroomId());
if (CollectionUtils.isEmpty(classroomList))
return;
List classroomIds = classroomList.stream().map(ClassroomList::getClassroomId).collect(Collectors.toList());
Map classroomMap = classroomList.stream().collect(Collectors.toMap(ClassroomList::getClassroomId, Function.identity()));
List data = logService.logExportData(param, classroomIds);
List userIds = data.stream().map(LogListDto::getCreateUserId).distinct().collect(Collectors.toList());
Map usernameMap = authService.list(new QueryWrapper().select("username", "user_id").in("user_id", userIds)).stream().collect(Collectors.toMap(IotSysUser::getUserId, IotSysUser::getUsername));
for (LogListDto log : data) {
ClassroomList classroom = classroomMap.get(log.getClassroomId());
log.setClassroomName(classroom.getClassroomName());
log.setSchoolName(classroom.getSchoolName());
log.setTeachingBuildingName(classroom.getTeachingBuildingName());
log.setCreateUserName(usernameMap.get(log.getCreateUserId()));
}
logger.info(" " + new Date().getMinutes() + "n" + new Date().getSeconds() + "s");
ListIterator iterator = data.listIterator();
while (iterator.hasNext()) {
int index = iterator.nextIndex();
LogListDto log = iterator.next();
log.setSort(String.valueOf(index));
csvPrinter.printRecord(log.getSort(), log.getLogType(), log.getRemark(), log.getSchoolName(), log.getTeachingBuildingName(), log.getClassroomName(), log.getCreateTime(), log.getCreateUserName());
}
logger.info(" " + new Date().getMinutes() + "n" + new Date().getSeconds() + "s");
data.clear();
outputStreamWriter.flush();
outputStreamWriter.close();
}