[英]Java SQL query memory leak
我有一个应用程序,它遍历大量 resultSet 并查询不同表中每一行的附加信息。
大致的结构是这样的:
public void main(String[] args) {
ResultSet result = database.connection.createStatement()
.executeQuery("SELECT * FROM entities");
ArrayList<Entity> entities = new ArrayList<Entity>();
while (result.next() {
Entity entity = EntityFactory.createById(result.getInt("id"));
entities.add(entity);
}
}
// EntityFactory
public static Entity createById(int id) {
StringBuilder sql = new StringBuilder("SELECT * FROM sampling_data WHERE id = ")
.append(id);
ResultSet result = database.connection.createStatement()
.executeQuery(sql.toString());
result.first();
EntityData data = new EntityData(25);
for (int sample = 1; sample <= 25; sample++) {
String sample_R = new StringBuilder("sample_")
.append(sample).append("_R").toString();
String sample_G = new StringBuilder("sample_")
.append(sample).append("_G").toString();
String sample_B = new StringBuilder("sample_")
.append(sample).append("_B").toString();
int r = resultSet.getInt(sample_R);
int g = resultSet.getInt(sample_G);
int b = resultSet.getInt(sample_B);
data.add(r, g, b);
}
return new Entity(data);
}
这会导致 OutOfMemoryException。
如何使循环(或整个方法)的内存效率更高?
从代码的一瞥中很难判断,但我认为这与总共提取的行太多有关。
您应该在具有合理行数(可能为 100)的Statement
上使用setFetchSize(int rows ) 。
private static int FETCH_SIZE = 100;
...
Statement stmt = databaseConnection.createStatement()
stmt.setFetchSize();
ResultSet result = stmt.executeQuery("SELECT * FROM sampling_data");
似乎 getInt() 方法在循环中执行时使用了大量内存。
这是不正确的。 getInt()
没有什么特别之处会导致您的问题。
您的架构打破了关系数据库的第一范式。 看到sample_1_R, sample_1_G, sample_1_B
让我质疑你的其他决定。 这显然是1:m
关系。 像 25 这样的神奇数字也是如此。
我想知道你为什么要用 String builder 和 ints 做所有这些事情。 我会将这些 RGB 值封装到一个有意义的对象中,例如java.awt.Color
。
我们在这里谈论多少数据?
25*3*32*2500 ~ 5.7 MB
这对于您的 2500 行来说并不多,每行都有 75 个整数值。 从您的代码中还不清楚正在发生的其他事情。
更新:
您在此代码中犯了经典的(n+1)
查询错误。 您获得所有实体,然后遍历它们以获取 RGB 值。 我建议做一个 JOIN 并立即将它们全部带回来。 这可能无法解释您的内存问题,但这是一个问题。
当您查询 RGB 值时,您会反复构建列名称。 那完全是浪费。 使它们成为数组中的static final String
实例。
最大的问题是(我认为)createById 没有关闭结果集和语句。 此外,没有 nx1 查询是有意义的。
try {
Statement stmt = database.connection.createStatement();
ResultSet result = stmt.executeQuery("SELECT * FROM sampling_data d"
+ " WHERE EXISTS(SELECT * FROM entities e WHERE e.id = d.id)");
List<Entity> entities = new ArrayList<Entity>();
while (result.next()) {
Entity entity = EntityFactory.createById(result);
entities.add(entity);
}
result.close();
stmt.close();
} catch (SQLException ex) {
Logger.getLogger(Test1.class.getName()).log(Level.SEVERE, null, ex);
}
和
// EntityFactory
public static Entity createById(ResultSet resultSet) {
EntityData data = new EntityData(25);
for (int sample = 1; sample <= 25; sample++) {
String sample_R = new StringBuilder("sample_").append(sample).append("_R").toString();
String sample_G = new StringBuilder("sample_").append(sample).append("_G").toString();
String sample_B = new StringBuilder("sample_").append(sample).append("_B").toString();
int r = resultSet.getInt(sample_R);
int g = resultSet.getInt(sample_G);
int b = resultSet.getInt(sample_B);
data.add(r, g, b);
}
return new Entity(data);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.