2012-04-22 3 views
0

У меня есть приложение, которое выполняет итерации по количеству результирующих наборов и запрашивает дополнительную информацию для каждой строки из другой таблицы.Ошибка памяти SQL SQL-запросов

Грубая структура такова:

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

О, вам нужно [VisualVM] (http://visualvm.java.net/) или такое ... Сколько результатов у вас там в 'ResultSet '? – yair

+0

У меня есть VisualVM, и это HeapDump показывает, что 'String' и' char [] 'используют около 95% кучи.Результирующий набор составляет около 2500 рядов, но в будущем он будет значительно больше. –

+1

В вашем основном методе вы запрашиваете один из этих 75 'sample_ *' столбцов или некоторых других столбцов? Хранить что-то вроде образцов RBG в базе данных и сопоставлять каждую выборку с собственным объектом, возможно, не лучшим образом. Какова общая цель, которую вы пытаетесь достичь здесь? –

ответ

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); 
} 
0

С проблесками кода сложно сказать, но я понимаю, что это связано со слишком большим количеством строк.

Вы должны использовать setFetchSize(int rows) на своем Statement с разумным количеством рядов (возможно, 100).

private static int FETCH_SIZE = 100; 
    ... 
    Statement stmt = databaseConnection.createStatement() 
    stmt.setFetchSize(); 
    ResultSet result = stmt.executeQuery("SELECT * FROM sampling_data"); 
0

кажется, что метод 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 экземплярами в массиве.

+0

Я отредактировал мой код и добавил все, что я ранее пропустил в комментариях. Может быть, теперь легче найти ошибку? –