数百万のデータをエクスポートする場合、適切な最適化手段を講じないと、実際にクラッシュやメモリ クラッシュなどの問題が発生する可能性があります。
これらの問題を回避するために、次の最適化手段を採用できます。
- データを一括読み込み:エクスポートするデータを複数のバッチに分割して読み書きし、その都度一部のデータを読み込み、Excel に書き込んだ直後にメモリをクリアします。これにより、すべてのデータを一度にロードすることによって引き起こされる過度のメモリ使用の問題を回避できます。
- ストリーミング書き込み方法を使用する: 結果セットをトラバースしながら、ストリーミング書き込み方法 (SXSSF など) を使用してデータを Excel テーブルに書き込み、一度にすべてのデータをメモリに書き込むことを避けます。
- 不要な接続を閉じる: コードを記述するときは、ResultSet、Statement、および Connection 接続を時間内に閉じて、リソースを解放し、システムの負担を軽減する必要があります。
- 適切なサーバー ハードウェア構成を使用する: エクスポートされるデータが大量の場合、システムの処理能力と速度を向上させるために、より多くの CPU とメモリを搭載した高性能サーバーを使用することをお勧めします。
- JVM メモリ割り当てを適切に設定する: JVM メモリ割り当てが不適切な場合、メモリ オーバーフローなどの問題が発生する可能性があります。JVM のメモリ割り当ては、-Xmx や -Xms などのパラメータを調整することで適切に設定できます。
次の依存関係を pom.xml ファイルに追加します。
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
</dependencies>
public void exportExcel() throws Exception{
// 加载驱动程序
Class.forName("com.mysql.cj.jdbc.Driver");
// 连接数据库
Connection conn = DriverManager.getConnection(url, username, password);
// 查询语句
String sql = "SELECT * FROM user";
Statement stmt = conn.createStatement();
ResultSet rs = null;
// 创建一个 Excel 文档
SXSSFWorkbook workbook = new SXSSFWorkbook(100);
try {
// 设置表格格式
Sheet sheet = workbook.createSheet("数据导出");
Row headerRow = sheet.createRow(0);
String[] headers = {
"ID", "姓名", "年龄"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
}
int rownum = 1;
while (true) {
rs = stmt.executeQuery(sql + " LIMIT " + rownum + ", 10000"); // 每次查询10000条数据
if (!rs.next()) { // 数据已经读取完
rs.close();
break;
}
do {
Row row = sheet.createRow(rownum++);
String id = rs.getString("id");
String name = rs.getString("name");
String age = rs.getString("age");
row.createCell(0).setCellValue(id);
row.createCell(1).setCellValue(name);
row.createCell(2).setCellValue(age);
} while (rs.next());
((SXSSFSheet) sheet).flushRows();
((SXSSFSheet) sheet).clearRowBreaks();
}
// 保存 Excel 文件
FileOutputStream out = new FileOutputStream("数据导出.xlsx");
workbook.write(out);
out.close();
} finally {
// 关闭连接
if (rs != null) { rs.close(); }
stmt.close();
conn.close();
// 释放资源
workbook.dispose();
}
}
バッチでのデータの読み取り、ストリーミング書き込みの使用、適切なキャッシュ サイズの設定、不要な接続のクローズなどの最適化手段により、コードの効率と安定性が大幅に向上しました。同時に、エクスポート時にすべてのデータを一度にエクスポートしないようにすることもお勧めします. 数百万のデータの場合は、上記の例のようにページに分けてエクスポートできます.