在我的Web应用程序中,用户可以编写自己的sql查询并可以创建数据集。我使用Apache Camel的REST组件和Spring JDBC与JdbcTemplate来执行查询。但是在执行查询时,返回大量记录(大约数百万),抛出以下堆栈跟踪引发异常:
val labeled = pca.transform(trainingDf).rdd.map(row => LabeledPoint(
row.getAs[Double]("label"),
row.getAs[org.apache.spark.mllib.linalg.Vector]("pcaFeatures")
))
以下是方式,我用来查询数据库并发送响应:
REST端点
org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange:...
.....
.....
Caused by: java.lang.OutOfMemoryError: Java heap space
执行查询的方法:
rest("/abc").consumes("application/json").produces("application/json")
.get("/xyz").to("bean:d?method=getXYZ(${body})").outTypeList(Map.class)
我尝试使用public List<Map<String,Object>> getXYZ(Map<String,Object> details) {
JdbcTemplate jdbc=new JdbcTemplate(ds); //ds is DataSource Object
List<Map<String,Object>> resultSet=jdbc.query(details.get("query").toString(), new RowMapper<Map<String,Object>>() {
@Override
public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
Map<String,Object> map = new HashMap<String,Object>();
DateFormat nice = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ResultSetMetaData meta = rs.getMetaData();
for(int i = 1; i <= meta.getColumnCount(); ++i) {
Object o = rs.getObject(i);
if(o instanceof Date) {
o = nice.format(o);
}
//put into map.
map.put(meta.getColumnLabel(i), o);
}
return map;
}
});
return resultSet;
}
设置获取大小,并尝试使用jdbc.setFetchSize(1000)
增加堆内存,但无法对其进行排序。
使用如此大的数据查询,获取和发送响应的最佳做法是什么?
什么是创建java.lang.OutOfMemoryError?
有没有办法在客户端压缩数据和自动解压缩?或流式传输结果集?
答案 0 :(得分:0)
OutOfMemory正在发生,因为大量对象被加载到您的应用程序中。
让我们假设只加载了String对象。 Java为每个字符存储2个字节,因此可以想象所有正在加载的字符串长度为5个字符。
让我们创建非常近似的计算。 5个字符的字符串对象是10个字节。其中1000个大约10千字节,1000000大约10兆字节。
我认为你的对象不仅仅是5个字符的字符串,所以你可以想象你的内存可以用得多快。
我强烈建议您将用户限制为有限的行数并引入分页。因此,即使用户没有在他的SQL中输入限制和偏移量,我也会以编程方式添加,以避免出现此问题。