我有一个应用程序迭代一定数量的resultSets并查询来自不同表的每一行的附加信息。
粗糙的结构是这样的:
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。
如何使循环(或整个方法)更节省内存?
答案 0 :(得分:0)
从代码的一瞥看起来有点难以理解,但我认为它与完全取出的行太多有关。
您应该在Statement
上使用setFetchSize(int rows),并且行数合理(可能为100行)。
private static int FETCH_SIZE = 100;
...
Statement stmt = databaseConnection.createStatement()
stmt.setFetchSize();
ResultSet result = stmt.executeQuery("SELECT * FROM sampling_data");
答案 1 :(得分:0)
似乎getInt()方法在执行时会占用大量内存 在循环中。
这是不正确的。 getInt()
导致您的问题没有什么特别之处。
您的架构打破了关系数据库的第一个常规形式。看到sample_1_R, sample_1_G, sample_1_B
也让我质疑你的其他决定。这显然是1:m
关系。同样适用于像25这样的魔术数字。
我想知道你为什么要使用String builder和int来做所有的事情。我将这些RGB值封装到一个有意义的对象中,如java.awt.Color
。
我们在这里谈论了多少数据?
25*3*32*2500 ~ 5.7 MB
这对你的2500行并不多,每行有75个整数值。还有一些其他事情正在发生,你的代码并不清楚。
更新
您在此代码中犯了经典的(n+1)
查询错误。您获得所有实体,然后循环它们以获取RGB值。我建议你做一个JOIN并立即把它们全部带回来。这可能无法解释您的记忆问题,但这是一个问题。
在查询RGB值时重复建立列名称。这完全是浪费。在数组中创建static final String
个实例。
答案 2 :(得分:0)
最大的问题是(我认为)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);
}