J'écris un programme complet d'extraction de base de données en Java. La base de données est Oracle, et c'est énorme. Certaines tables ont ~ 260 millions d'enregistrements. Le programme devrait créer un fichier par table dans un format spécifique, donc utiliser Oracle datapump etc n'est pas une option. En outre, certaines stratégies de sécurité de l'entreprise ne permettent pas d'écrire une procédure PL/SQL pour créer des fichiers sur le serveur de base de données pour cette exigence. Je dois aller avec Java et JDBC.Comment surmonter OutOfMemoryError lors de l'écriture de gros fichiers
Le problème auquel je suis confronté est que depuis que les fichiers pour certains de la table est énorme (~ 30 Go), je suis à court de mémoire presque à chaque fois, même avec un tas Java de 20 Go. Lors de la création d'un fichier lorsque la taille du fichier dépasse la taille du segment, même avec l'une des stratégies GC les plus agressives, le processus semble se bloquer. Par exemple, si la taille du fichier est supérieure à 20 Go et la taille du segment de mémoire de 20 Go, une fois que l'utilisation du tas atteint la taille maximum, elle ralentit l'écriture de 2 Mo par minute.
Je cherche un moyen de surmonter ce problème. Toute aide serait grandement appréciée.
Voici quelques détails de la configuration du système que j'ai: Java - JDK1.6.0_14
configuration système - RH Enterprise Linux (2.6.18) fonctionnant sur 4 X Intel Xeon E7450 (6 cœurs) @ 2,39 GH
RAM - 32 Go
Oracle Database 11g
fichierwirting partie du code ci-dessous va:
private void runQuery(Connection conn, String query, String filePath,
String fileName) throws SQLException, Exception {
PreparedStatement stmt = null;
ResultSet rs = null;
try {
stmt = conn.prepareStatement(query,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(maxRecBeforWrite);
rs = stmt.executeQuery();
// Write query result to file
writeDataToFile(rs, filePath + "/" + fileName, getRecordCount(
query, conn));
} catch (SQLException sqle) {
sqle.printStackTrace();
} finally {
try {
rs.close();
stmt.close();
} catch (SQLException ex) {
throw ex;
}
}
}
private void writeDataToFile(ResultSet rs, String tempFile, String cnt)
throws SQLException, Exception {
FileOutputStream fileOut = null;
int maxLength = 0;
try {
fileOut = new FileOutputStream(tempFile, true);
FileChannel fcOut = fileOut.getChannel();
List<TableMetaData> metaList = getMetaData(rs);
maxLength = getMaxRecordLength(metaList);
// Write Header
writeHeaderRec(fileOut, maxLength);
while (rs.next()) {
// Now iterate on metaList and fetch all the column values.
writeData(rs, metaList, fcOut);
}
// Write trailer
writeTrailerRec(fileOut, cnt, maxLength);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
fileOut.close();
} catch (IOException ioe) {
fileOut = null;
throw new Exception(ioe.getMessage());
}
}
}
private void writeData(ResultSet rs, List<TableMetaData> metaList,
FileChannel fcOut) throws SQLException, IOException {
StringBuilder rec = new StringBuilder();
String lf = "\n";
for (TableMetaData tabMeta : metaList) {
rec.append(getFormattedString(rs, tabMeta));
}
rec.append(lf);
ByteBuffer byteBuf = ByteBuffer.wrap(rec.toString()
.getBytes("US-ASCII"));
fcOut.write(byteBuf);
}
private String getFormattedString(ResultSet rs, TableMetaData tabMeta)
throws SQLException, IOException {
String colValue = null;
// check if it is a CLOB column
if (tabMeta.isCLOB()) {
// Column is a CLOB, so fetch it and retrieve first clobLimit chars.
colValue = String.format("%-" + tabMeta.getColumnSize() + "s",
getCLOBString(rs, tabMeta));
} else {
colValue = String.format("%-" + tabMeta.getColumnSize() + "s", rs
.getString(tabMeta.getColumnName()));
}
return colValue;
}
Vous n'avez fourni aucun code, ce qui rend difficile de dire exactement ce que vous faites mal ... –
Si vous diffusez les enregistrements dans un fichier vous ne devriez pas avoir de problème, il n'y a aucune raison de conserver une table entière de 2 Go en mémoire avant de l'écrire dans un fichier. –
Vérifiez également comment vous utilisez des chaînes dans votre code. Sans code, il est difficile de suggérer des solutions. –