私はこれまでに何度も尋ねられてきた同様の質問をしていますが、解決策の多くを試したとしても、私はまだこの問題を抱えています。Java PreparedStatement java.lang.OutOfMemoryError:GCオーバーヘッドの上限を超えました
私たちのアプリケーションでは、パラメータ化された生のSQLクエリーを作成して、エクセルのスプレッドシートにダウンロードされたDBからデータを抽出することができます。
小さいデータセットの場合、これはうまくいきますが、ファイルサイズが10MBに近づくと、この問題が発生します。
データセットは、100k行または80-90mbの可能性があります。可能であれば、JVMヒープサイズを増やしたくありません。
私のコードには目に見えない目障りなエラーがあります。 resultSet.next()ループが問題の原因になっているようです。ヒープスペースを不安定にするのを防ぐためにこれを書くより効率的な方法はありますか?
ご迷惑をおかけして申し訳ございません。あなたは全体のResultSetをロードしているため、クエリの結果は大量のデータを返す場合のおかげ
/*
*
* query is a raw sql query that takes parameters (using Mybatis)
* criteriaMap the arguments that we subsitute into the query
*
*/
public List<Map<String, Object>> queryForJsonWithoutMapping(final String query, final Map<String, Object> criteriaMap){
SqlSession sqlSession = getSqlSessionInstance();
String sql = "";
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
try {
final Configuration configuration = getSqlSessionInstance().getConfiguration();
SqlSourceBuilder builder = new SqlSourceBuilder(configuration);
SqlSource src = builder.parse(query, Map.class, null);
BoundSql boundSql = src.getBoundSql(criteriaMap);
sql = boundSql.getSql();
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
connection = sqlSession.getConnection();
pstmt = connection.prepareStatement(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
// this function subs the params into the preparedStatement query
buildParams(parameterMappings, criteriaMap, pstmt);
resultSet = pstmt.executeQuery();
// the while loop inside this function is where things start to hang
List<Map<String, Object>> results = getObjectFromResultSet(resultSet);
return results;
} catch (Exception e) {
LOG.error(e.getMessage(), e);
LOG.error(ExceptionUtils.getStackTrace(e));
throw new IllegalStateException(sql + " " + e.getMessage(), e);
} finally {
try{
connection.close();
pstmt.close();
resultSet.close();
}catch (SQLException e){
e.printStackTrace();
}
sqlSession.close();
}
private List<Map<String, ?>> getEntitiesFromResultSet(ResultSet resultSet) throws SQLException {
ArrayList<Map<String, ?>> entities = new ArrayList<>(resultSet.getFetchSize());
int index = 0;
Map<String, Object> jsonObject;
while (resultSet.next()) {
jsonObject = getEntityFromResultSet(resultSet);
entities.add(index, jsonObject);
index ++;
}
resultSet.close();
return entities;
}
private List<Map<String, Object>> getObjectFromResultSet(ResultSet resultSet) throws SQLException {
ArrayList<Map<String, Object>> entities = new ArrayList<>(resultSet.getFetchSize());
int index = 0;
Map<String, Object> jsonObject;
while (resultSet.next()) {
jsonObject = getEntityFromResultSet(resultSet);
entities.add(index, jsonObject);
index ++;
}
resultSet.close();
return entities;
}
DBは、いくつかの点でメモリのうち、このようなデザイン、あなたは意志必然的な実行でOracle
伝統的な「メモリにすべてを読み込んでから、何かをやり始めます」のように見えます。あなたは読んでいるときに結果を流すことができます、それはずっと効率的です。 – Kayaman
entities.add(index、jsonObject);これが原因です。高速でそのメモリを利用する – Olu