我制作了将DB迁移到DB的Java程序。 这会生成oom。 我该怎么做才能返回内存?
我退回垃圾回收。 因此,我看到我正在使用的内存正在缩小。 但是,当数据量很大时,垃圾回收无济于事。
private void insertIntoTable(Connection con, ResultSet rs, String targetTable) {
PreparedStatement pstmt = null;
int batchSize = 50000;
String insertSql = createInsertSql(targetTable);
Blob blob = null;
try {
pstmt = con.prepareStatement(insertSql);
int i = 0;
while (rs.next()) {
i++;
int j = 0;
for (String key : colMap.keySet()) {
if (colMap.get(key).contains("TIMESTAMP")) {
pstmt.setTimestamp(++j, rs.getTimestamp(key));
} else if (colMap.get(key).contains("DATE")) {
pstmt.setDate(++j, rs.getDate(key));
} else if (colMap.get(key).contains("BLOB")) {
if(blob==null) {
blob = con.createBlob();
}
blob.setBytes(1, rs.getBytes(key));
pstmt.setBlob(++j, blob);
} else {
pstmt.setString(++j, rs.getString(key));
}
}
pstmt.addBatch();// addBatch에 담기
pstmt.clearParameters();// 파라미터 Clear
if ((i % batchSize) == 0) {
System.out.print("★");
pstmt.executeBatch();
pstmt.clearBatch();
con.commit();
}
}
System.out.println("★\ncount:\t" + i);
System.out.println();
pstmt.executeBatch();
con.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
if (rs != null)
try {
rs.close();
rs = null;
} catch (SQLException ex) {
}
if (pstmt != null)
try {
pstmt.close();
pstmt = null;
} catch (SQLException ex) {
}
}
}
我想一次迁移由内存返回的大量数据,效果很好。
答案 0 :(得分:1)
发生这种情况是因为批量太大。
解决方案:
有一种方法可以定义最大批处理大小,但是问题在于大多数数据库驱动程序都没有实现该方法。
因此,您需要维护.addBatch()
和方法调用的计数,然后需要以100或1000的计数执行该批处理,这与应用程序资源的容量相同。
所以,这里的问题是批处理量太大(50000)